1 // Simple application that creates a server socket, listening for connections
2 // of the unattended install test. Once it gets a client connected, the
3 // app will send back an ACK string, indicating the install process is done.
4 //
5 // You must link this code with Ws2_32.lib, Mswsock.lib, and Advapi32.lib
6 //
7 // Author: Lucas Meneghel Rodrigues <lmr@redhat.com>
8 // Code was adapted from an MSDN sample.
9
10 // Usage: finish.exe
11
12 #ifdef __MINGW32__
13 #undef _WIN32_WINNT
14 #define _WIN32_WINNT 0x500
15 #endif
16
17 #include <windows.h>
18 #include <winsock2.h>
19 #include <ws2tcpip.h>
20 #include <stdlib.h>
21 #include <stdio.h>
22
23 int DEFAULT_PORT = 12323;
24
ExitOnError(const char * message,BOOL winsock=FALSE)25 void ExitOnError(const char *message, BOOL winsock = FALSE)
26 {
27 LPVOID system_message;
28 char buffer[512];
29 int error_code;
30
31 if (winsock)
32 error_code = WSAGetLastError();
33 else
34 error_code = GetLastError();
35 WSACleanup();
36
37 FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
38 FORMAT_MESSAGE_FROM_SYSTEM,
39 NULL,
40 error_code,
41 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
42 (LPTSTR)&system_message,
43 0,
44 NULL);
45
46 sprintf(buffer,
47 "%s!\n"
48 "Error code = %d\n"
49 "Error message = %s",
50 message, error_code, (char *)system_message);
51
52 MessageBox(NULL, buffer, "Error", MB_OK | MB_ICONERROR);
53
54 LocalFree(system_message);
55 ExitProcess(1);
56 }
57
PrepareListenSocket(int port)58 SOCKET PrepareListenSocket(int port)
59 {
60 sockaddr_in addr;
61 linger l;
62 int result;
63
64 // Create socket
65 SOCKET ListenSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
66 if (ListenSocket == INVALID_SOCKET)
67 ExitOnError("Socket creation failed", TRUE);
68
69 // Enable lingering
70 l.l_linger = 10;
71 l.l_onoff = 1;
72 setsockopt(ListenSocket, SOL_SOCKET, SO_LINGER, (char *)&l, sizeof(l));
73
74 // Bind the socket
75 addr.sin_family = AF_INET;
76 addr.sin_addr.s_addr = htonl(INADDR_ANY);
77 addr.sin_port = htons(port);
78
79 result = bind(ListenSocket, (sockaddr *)&addr, sizeof(addr));
80 if (result == SOCKET_ERROR)
81 ExitOnError("Bind failed", TRUE);
82
83 // Start listening for incoming connections
84 result = listen(ListenSocket, SOMAXCONN);
85 if (result == SOCKET_ERROR)
86 ExitOnError("Listen failed", TRUE);
87
88 return ListenSocket;
89 }
90
main(int argc,char ** argv)91 int main(int argc, char **argv)
92 {
93 WSADATA wsaData;
94 SOCKET ListenSocket = INVALID_SOCKET, ClientSocket = INVALID_SOCKET;
95 struct addrinfo *result = NULL, hints;
96 char *sendbuf = "done";
97 int iResult, iSendResult;
98
99 // Validate the parameters
100 if (argc != 1) {
101 ExitOnError("Finish.exe takes no parameters", FALSE);
102 }
103
104 // Initialize Winsock
105 iResult = WSAStartup(MAKEWORD(2,2), &wsaData);
106 if (iResult != 0) {
107 ExitOnError("WSAStartup failed", FALSE);
108 }
109
110 // Resolve the server address and port
111 ListenSocket = PrepareListenSocket(DEFAULT_PORT);
112
113 // Accept a client socket
114 ClientSocket = accept(ListenSocket, NULL, NULL);
115 if (ClientSocket == INVALID_SOCKET) {
116 closesocket(ListenSocket);
117 ExitOnError("Accept failed", TRUE);
118 }
119
120 // No longer need the server socket
121 closesocket(ListenSocket);
122
123 // Send the ack string to the client
124 iSendResult = send(ClientSocket, sendbuf, sizeof(sendbuf), 0);
125 if (iSendResult == SOCKET_ERROR) {
126 closesocket(ClientSocket);
127 ExitOnError("Send failed", TRUE);
128 }
129 // Report the number of bytes sent
130 printf("Bytes sent: %d\n", iSendResult);
131
132 // Shutdown the connection since we're done
133 iResult = shutdown(ClientSocket, SD_SEND);
134 if (iResult == SOCKET_ERROR) {
135 closesocket(ClientSocket);
136 ExitOnError("Shutdown failed", TRUE);
137 }
138
139 // Cleanup
140 closesocket(ClientSocket);
141 WSACleanup();
142
143 return 0;
144 }
145