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
23int DEFAULT_PORT = 12323;
24
25void 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
58SOCKET 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
91int 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