/* * Create a loopback socket and set it up to listen on the specified * port. Return the new socket or INVALID_SOCKET if there's an error. */ SOCKET sysCreateServerSocket(int port) { SOCKET server; SOCKADDR_IN iname = {0}; int length = sizeof(iname); sysInitSocketLibrary(); iname.sin_family = AF_INET; iname.sin_port = htons((u_short)port); iname.sin_addr.s_addr = inet_addr("127.0.0.1"); if ((server = socket(AF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET) { return INVALID_SOCKET; } if (bind(server, (SOCKADDR *)&iname, sizeof(iname)) == SOCKET_ERROR) { sysCloseSocket(server); return INVALID_SOCKET; } if (listen(server, SOMAXCONN) == SOCKET_ERROR) { sysCloseSocket(server); return INVALID_SOCKET; } return server; }
/* * Tests creatability of a loopback socket for the specified port. * If the test fails, INVALID_SOCKET is returned, otherwise the * would-be socket is returned. For the special case *port == 0, * the port will be reset to an ephemeral port (chosen by the kernel). */ SOCKET sysTestServerSocketCreatable(int* port) { SOCKET sock; SOCKADDR_IN iname = {0}; int length = sizeof(iname); sysInitSocketLibrary(); iname.sin_family = AF_INET; iname.sin_port = htons((u_short)*port); iname.sin_addr.s_addr = inet_addr("127.0.0.1"); if ((sock = socket(AF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET) { return INVALID_SOCKET; } /* When bind() is called and *port==0, kernel will choose ephemeral port */ if (bind(sock, (SOCKADDR *)&iname, sizeof(iname)) == SOCKET_ERROR) { sysCloseSocket(sock); return INVALID_SOCKET; } /* When getsockname() is called, iname is updated to reflect port used by kernel */ if (getsockname(sock, (SOCKADDR *)&iname, &length) == SOCKET_ERROR) { sysCloseSocket(sock); return INVALID_SOCKET; } /* At this juncture, we have a valid socket and a valid (possibly ephemeral) port */ *port = ntohs(iname.sin_port); sysCloseSocket(sock); return sock; }
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { static int width = 0, height = 0; switch (message) { case WM_CONNECT: { SOCKADDR_IN iname; int length = sizeof(iname); SOCKET client; char cmd[1]; if ((client = accept(server, (SOCKADDR *)&iname, &length)) == -1) { errorExit(getMsgString(MSG_ACCEPT_FAILED)); } if (recv(client, cmd, 1, 0) == 1) { switch(cmd[0]) { case 'Z': sysCloseSocket(client); splashExit(); break; default: errorExit(getMsgString(MSG_SPLASH_CMND)); } } } case WM_DESTROY: { splashExit(); break; } default: { return DefWindowProc(hWnd, message, wParam, lParam); } } return 0; }
/* * Create a loopback socket connected to the specified port. Return the * new socket or INVALID_SOCKET if there's an error. */ SOCKET sysCreateClientSocket(int port) { SOCKET client; SOCKADDR_IN iname = {0}; sysInitSocketLibrary(); iname.sin_family = AF_INET; iname.sin_port = htons((u_short)port); iname.sin_addr.s_addr = inet_addr("127.0.0.1"); if ((client = socket(AF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET) { return INVALID_SOCKET; } if (connect(client, (SOCKADDR *)&iname, sizeof(iname)) == SOCKET_ERROR) { sysCloseSocket(client); return INVALID_SOCKET; } return client; }
int sysSplash(int splashPort, char *splashFile) { WNDCLASS wce = {0}; HWND hWnd; MSG msg; int port; int ud = CW_USEDEFAULT; HINSTANCE hInstance = GetModuleHandle(NULL); if ((server = sysCreateListenerSocket(&port)) == INVALID_SOCKET) { errorExit(getMsgString(MSG_LISTENER_FAILED)); } /* Send our ephemeral port back to the parent process. The parent * process port number is splashPort. We send the port number back * to the parent as a 6 character string. */ { SOCKADDR_IN iname = {0}; SOCKET parent; HWND hWnd = NULL; char data[6]; if (splashPort <= 0) { errorExit(getMsgString(MSG_SPLASH_PORT)); } if ((parent = sysCreateClientSocket(splashPort)) == INVALID_SOCKET) { errorExit(getMsgString(MSG_SPLASH_SOCKET)); } sprintf(data, "%d", port); if (send(parent, data, 6, 0) != 6) { errorExit(getMsgString(MSG_SPLASH_SEND)); } sysCloseSocket(parent); } /* Check for NO Splash mode */ if (splashFile == NULL) { return 0; } // create a dummy window to get events on: wce.style = 0; wce.lpfnWndProc = (WNDPROC)WndProc; wce.hInstance = hInstance; wce.hCursor = LoadCursor(NULL, IDC_ARROW); wce.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); wce.lpszClassName = "SplashDummy"; RegisterClass(&wce); hWnd = CreateWindow("SplashDummy", "Win32Splash", WS_OVERLAPPEDWINDOW, ud, ud, ud, ud, NULL, NULL, hInstance, NULL); /* Set a timer that will exit this process after TIMEOUT seconds */ if (SetTimer(hWnd, 0, TIMEOUT * 1000, (TIMERPROC)timeoutProc) == 0) { errorExit(getMsgString(MSG_SPLASH_TIMER)); } DoSplashInit(); DoSplashLoadFile(splashFile); /* Ask Win32 to notify us when there are pending connections on the * server socket. WM_CONNECT is an "event" defined here. */ WSAAsyncSelect(server, hWnd, WM_CONNECT, FD_ACCEPT); while (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } //return msg.wParam; return 0; }