singrdk/base/Windows/gulpserver/gulpserver.c

337 lines
9.5 KiB
C
Raw Normal View History

2008-03-05 09:52:00 -05:00
#include "winlean.h"
#include "winsock2.h"
#include <stdlib.h>
#include <stdio.h>
#define DEF_PACKET_SIZE 32
#define MAX_PACKET 1024
#define xmalloc(s) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, (s))
#define xfree(p) HeapFree (GetProcessHeap(), 0, (p))
2008-11-17 18:29:00 -05:00
//
// This event is set when a control socket is closed before the end of a test.
// If the user kills the manager script then its end of the control socket will
// be closed. We catch that and use this event to notify any worker threads
// associated with that control socket to stop what they're doing.
//
2008-03-05 09:52:00 -05:00
_declspec (thread) void * MC_MyCS_StopEvent;
2008-11-17 18:29:00 -05:00
// print an error message and exit the program
2008-03-05 09:52:00 -05:00
void die (char *format,...) {
va_list args;
char buffer[2048], *ptr=buffer;
va_start(args,format);
ptr += vsprintf (ptr, format, args);
va_end (args);
*(ptr++) = '\n';
*(ptr++) = '\0';
printf( buffer);
exit(1);
}
int InitChildLayer(void) {
WORD wVersionRequested;
WSADATA wsaData;
int err;
int major, minor;
wVersionRequested = MAKEWORD( 2, 0 );
err = WSAStartup( wVersionRequested, &wsaData );
if ( err != 0 ) {
2008-11-17 18:29:00 -05:00
// Tell the user that we couldn't find a useable
// WinSock DLL.
2008-03-05 09:52:00 -05:00
die ("Couldn't find a WinSock DLL!\n");
}
2008-11-17 18:29:00 -05:00
// Confirm that the WinSock DLL supports 2.0.
// Note that if the DLL supports versions greater
// than 2.0 in addition to 2.0, it will still return
// 2.0 in wVersion since that is the version we
// requested.
2008-03-05 09:52:00 -05:00
major = LOBYTE( wsaData.wVersion );
minor = LOBYTE( wsaData.wVersion );
if ( major < 1 || ( major == 1 && minor < 1 ) ) {
2008-11-17 18:29:00 -05:00
// Tell the user that we couldn't find a useable
// WinSock DLL.
2008-03-05 09:52:00 -05:00
WSACleanup( );
die ("Require at least WinSock 1.1, your version is %d.%d!\n",
major, minor);
}
return 0;
}
static USHORT
checksum(USHORT *buffer, int size)
{
unsigned long cksum=0;
while(size > 1)
{
cksum += *buffer++;
size -= sizeof(USHORT);
}
if (size)
2008-11-17 18:29:00 -05:00
cksum += *(UCHAR*)buffer; // if there's an odd number of bytes
2008-03-05 09:52:00 -05:00
cksum = (cksum >> 16) + (cksum & 0xffff);
cksum += (cksum >> 16);
return (USHORT)(~cksum);
}
2008-11-17 18:29:00 -05:00
//
// MC_GetLastErrorText
//
// PURPOSE: copies error message text to string
//
// PARAMETERS:
// lpszBuf - destination buffer
// dwSize - size of buffer
//
// RETURN VALUE:
// destination buffer
//
2008-03-05 09:52:00 -05:00
LPSTR
MC_GetLastErrorText(LPSTR lpszBuf, DWORD dwSize, DWORD errnum)
{
DWORD dwRet;
LPTSTR lpszTemp = NULL;
dwRet = FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |FORMAT_MESSAGE_ARGUMENT_ARRAY,
NULL,
errnum,
LANG_NEUTRAL,
(LPTSTR)&lpszTemp,
0,
NULL );
if ( !dwRet)
2008-11-17 18:29:00 -05:00
sprintf(lpszBuf, "error number %d", errnum); // no message so use errnum
2008-03-05 09:52:00 -05:00
else
{
2008-11-17 18:29:00 -05:00
lpszTemp[lstrlen(lpszTemp)-2] = '\0'; // remove cr and newline characters
2008-03-05 09:52:00 -05:00
sprintf(lpszBuf, "%s (0x%x)", lpszTemp, errnum);
}
if (lpszTemp)
LocalFree((HLOCAL) lpszTemp );
return lpszBuf;
}
static void
MC_ErrMsg(LPSTR buf, DWORD bufsize, LPCSTR msg)
{
DWORD tmp;
tmp = strlen(strcpy(buf, msg));
MC_GetLastErrorText(buf + tmp, bufsize - tmp, WSAGetLastError());
}
2008-11-17 18:29:00 -05:00
//
// FUNCTION: MC_Recv
//
// PURPOSE: A replacement for the Winsock recv() routine. This version uses
// overlapped I/O to look for data on a socket and also watch
// for the Stop event.
//
// PARAMETERS:
// sock - read from this socket.
// buffer - place incoming data into this buffer.
// nbytes - the amount of storage in the buffer.
//
// RETURN VALUE:
// -1 - error.
// 0 - the socket connection has been closed.
// >0 - the number of bytes read.
//
2008-03-05 09:52:00 -05:00
int
MC_Recv(SOCKET sock, char *buffer, int nbytes)
{
DWORD bytesreceived;
DWORD flags = 0;
WSAOVERLAPPED ov;
WSABUF wsabuffer[1];
HANDLE ourevents[2];
ov.hEvent = NULL;
ov.Offset = ov.OffsetHigh = 0;
wsabuffer[0].buf = buffer;
wsabuffer[0].len = nbytes;
while(1)
{
if (WSARecv(sock, wsabuffer, 1, &bytesreceived, &flags, &ov, NULL) == SOCKET_ERROR)
{
switch (WSAGetLastError())
{
2008-11-17 18:29:00 -05:00
case WSAEWOULDBLOCK: continue; // try again
2008-03-05 09:52:00 -05:00
case WSAENETRESET:
case WSAECONNRESET:
2008-11-17 18:29:00 -05:00
case WSAEDISCON: return 0; // connection closed
2008-03-05 09:52:00 -05:00
//case WSA_IO_PENDING: break; /* okay */
2008-11-17 18:29:00 -05:00
default: return -1; // unexpected error
2008-03-05 09:52:00 -05:00
}
ourevents[0] = (HANDLE) sock;
ourevents[1] = MC_MyCS_StopEvent;
if (WaitForMultipleObjects(2, ourevents, FALSE, INFINITE) != WAIT_OBJECT_0)
{
printf("MC_Recv(): Stop event or WaitForMultipleObjects() error\n");
2008-11-17 18:29:00 -05:00
return -1; // Stop event or error
2008-03-05 09:52:00 -05:00
}
else if (!WSAGetOverlappedResult(sock, &ov, &bytesreceived, FALSE, &flags))
2008-11-17 18:29:00 -05:00
return -1; // error
2008-03-05 09:52:00 -05:00
}
2008-11-17 18:29:00 -05:00
return bytesreceived; // if we got here its due to a successful read
2008-03-05 09:52:00 -05:00
}
}
static DWORD WINAPI Gulp(LPVOID lpParam )
{
int totalBytes;
int numPackets;
int bytesRead;
char buffer[4096];
SOCKET sockfd;
INT64 startCounter, endCounter, frequency;
totalBytes = 0;
numPackets = 0;
sockfd = *(SOCKET *) lpParam;
QueryPerformanceCounter((PLARGE_INTEGER)&startCounter);
do {
bytesRead = MC_Recv(sockfd, buffer, 4096);
if (bytesRead > 0 ) {
numPackets++;
totalBytes += bytesRead;
}
} while (bytesRead > 0) ;
QueryPerformanceCounter((PLARGE_INTEGER)&endCounter);
QueryPerformanceFrequency((PLARGE_INTEGER)&frequency);
printf(" Read %d bytes / %d KB / %d MB in %d receives\n",
totalBytes, totalBytes / 1024, totalBytes / 1048576, numPackets);
if (endCounter != startCounter) {
double tau = (double)(endCounter - startCounter) / (double)frequency;
double bps = totalBytes * 8.0 / tau;
printf("Transferred in %.3e seconds => %.3e bps\n",
tau, bps);
}
else {
printf("Transfer too quick to measure with this clock\n");
}
return 1;
}
static DWORD listener (int port, LPSTR retmsg, DWORD size_retmsg)
{
struct sockaddr_in sock_addr;
DWORD tmp;
int server_status = 0;
int ret_count = 0;
SOCKET listenSockfd;
SOCKET sockfd;
HANDLE hThread;
DWORD dwThreadId;
memset((void *) &sock_addr, '\0', sizeof(sock_addr));
sock_addr.sin_family = AF_INET;
sock_addr.sin_addr.S_un.S_addr = INADDR_ANY;
sock_addr.sin_port = htons((short) (port > 0 ? port : 80));
if ((listenSockfd = WSASocket(AF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, 0, 0)) == INVALID_SOCKET)
{
MC_ErrMsg(retmsg, size_retmsg, "500 Unable to create socket: ");
printf(retmsg);
return -1;
}
if ((listenSockfd = WSASocket(AF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, 0, 0)) == INVALID_SOCKET)
{
MC_ErrMsg(retmsg, size_retmsg, "500 Unable to create socket: ");
printf(retmsg);
return -1;
}
tmp = bind(listenSockfd, (struct sockaddr *) &sock_addr, sizeof(sock_addr));
if (tmp == SOCKET_ERROR)
{
MC_ErrMsg(retmsg, size_retmsg, "500 Unable to bind to socket: ");
printf(retmsg);
return -1;
}
tmp = listen( listenSockfd,10);
if (tmp == SOCKET_ERROR)
{
MC_ErrMsg(retmsg, size_retmsg, "500 Unable to listen on socket: ");
printf(retmsg);
return -1;
}
do {
printf("\n listening\n");
sockfd = accept(listenSockfd,0,0);
if (sockfd == SOCKET_ERROR)
{
MC_ErrMsg(retmsg, size_retmsg, "500 Unable to accept on socket: ");
printf(retmsg);
return -1;
}
printf(" ...Accepted connection\n");
hThread = CreateThread(
NULL, // default security attributes
0, // use default stack size
Gulp, // thread function
&sockfd, // argument to thread function
0, // use default creation flags
&dwThreadId); // returns the thread identifier
// Check the return value for success.
if (hThread == NULL)
{
printf("CreateThread failed." );
}
else
{
CloseHandle( hThread );
}
} while (TRUE);
}
int main(int argc, char *argv[]) {
char retmsg[1024];
int foo;
if (argc < 2 ) {
printf("gulpserver port\n");
printf(" listens on port for TCP blast client \n");
return -1;
}
foo = atoi(argv[1]);
InitChildLayer();
printf (" Listening on port %d ...",foo);
listener(foo, retmsg, 1024);
WSACleanup( );
}