GLOBCHAT.C
资源名称:MSDN_VC98.zip [点击查看]
上传用户:bangxh
上传日期:2007-01-31
资源大小:42235k
文件大小:29k
源码类别:
Windows编程
开发平台:
Visual C++
- // THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
- // ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
- // THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
- // PARTICULAR PURPOSE.
- //
- // Copyright (C) 1993-1997 Microsoft Corporation. All Rights Reserved.
- //
- // MODULE: generic.c
- //
- // PURPOSE: Implement the windows procedure for the main application
- // windows. Also implement the generic message and command dispatchers.
- //
- // FUNCTIONS:
- // WndProc - Processes messages for the main window.
- // MsgCreate - Handles the WM_CREATE message. Sets up Display and
- // initializes listening sockets. Also advertises the
- // service
- // MsgSize - Resizes the Listboxes to fit nicely in main window.
- // MsgTimer - Handles the WM_TIMER messages which alert us to the
- // fact that its time to send a SAP packet
- // MsgConnected - Handles new connection notifications
- // MsgDataready - Handles recv data notifications and close socket
- // notifications
- // MsgCommand - Handle the WM_COMMAND messages for the main window.
- // MsgDestroy - Handles the WM_DESTROY message by calling
- // PostQuitMessage().
- // CmdExit - Handles the file exit command by calling destory
- // window on the main window.
- //
- // COMMENTS:
- //
- #include <windows.h> // required for all Windows applications
- #include <windowsx.h>
- #include <wsipx.h>
- #include <wsnetbs.h>
- #include <svcguid.h>
- #include "globals.h" // prototypes specific to this application
- // Main window message table definition.
- MSD rgmsd[] =
- {
- {WM_CREATE, MsgCreate},
- {WM_SIZE, MsgSize},
- {WM_TIMER, MsgTimer},
- {WM_COMMAND, MsgCommand},
- {WM_DESTROY, MsgDestroy},
- {MW_CONNECTED, MsgConnected},
- {MW_DATAREADY, MsgDataready}
- };
- MSDI msdiMain =
- {
- sizeof(rgmsd) / sizeof(MSD),
- rgmsd,
- edwpWindow
- };
- // Main window command table definition.
- CMD rgcmd[] =
- {
- {IDM_EXIT, CmdExit},
- {IDM_ABOUT, CmdAbout}
- };
- CMDI cmdiMain =
- {
- sizeof(rgcmd) / sizeof(CMD),
- rgcmd,
- edwpWindow
- };
- //
- // FUNCTION: WndProc(HWND, UINT, WPARAM, LPARAM)
- //
- // PURPOSE: Processes messages for the main window.
- //
- // PARAMETERS:
- // hwnd - window handle
- // uMessage - message number
- // wparam - additional information (dependant on message number)
- // lparam - additional information (dependant on message number)
- //
- // RETURN VALUE:
- // The return value depends on the message number. If the message
- // is implemented in the message dispatch table, the return value is
- // the value returned by the message handling function. Otherwise,
- // the return value is the value returned by the default window procedure.
- //
- // COMMENTS:
- // Call the DispMessage() function with the main window's message dispatch
- // information (msdiMain) and the message specific information.
- //
- LRESULT CALLBACK WndProc(HWND hwnd,
- UINT uMessage,
- WPARAM wparam,
- LPARAM lparam)
- {
- return DispMessage(&msdiMain, hwnd, uMessage, wparam, lparam);
- }
- //
- // FUNCTION: MsgCreate(HWND, UINT, WPARAM, LPARAM)
- //
- // PURPOSE: Sets up child windows, initializes listening sockets, and advertises
- // the existence of the service
- //
- // PARAMETERS:
- //
- // hwnd - Window handle
- // uMessage - Message number (Unused)
- // wparam - Extra data (Unused)
- // lparam - Extra data (Unused)
- //
- // RETURN VALUE:
- //
- // Always returns 0 - Message handled
- //
- // COMMENTS:
- //
- //
- LRESULT MsgCreate(HWND hwnd, UINT uMessage, WPARAM wparam, LPARAM lparam)
- {
- int sizeProtBuf = 0;
- int cNumProt;
- int j, k;
- int GoodProts[40];
- WORD wVersionRequested;
- WSADATA wsaData;
- char outtext[80];
- int tabwidth[1] = {100};
- BOOL bcaststat;
- int addrlen;
- // Create Protocol listbox
- hwndProtocolList = CreateWindow("LISTBOX",
- NULL,
- WS_BORDER | WS_CHILD | WS_VISIBLE | LBS_STANDARD | LBS_USETABSTOPS,
- 0, 0, 0, 0,
- hwnd,
- (HMENU)ID_PROTOCOLBOX,
- (HINSTANCE) GetWindowLong(hwnd, GWL_HINSTANCE),
- 0);
- // Set tabs
- SendMessage(hwndProtocolList, LB_SETTABSTOPS, 1, (LPARAM)tabwidth);
- // Create Client List listbox
- hwndClientList = CreateWindow("LISTBOX",
- NULL,
- WS_BORDER | WS_CHILD | WS_VISIBLE | LBS_STANDARD | LBS_USETABSTOPS | LBS_HASSTRINGS,
- 0, 0, 0, 0,
- hwnd,
- (HMENU)ID_CLIENTBOX,
- (HINSTANCE) GetWindowLong(hwnd, GWL_HINSTANCE),
- 0);
- // Set tab stops
- SendMessage(hwndClientList, LB_SETTABSTOPS, 1, (LPARAM)tabwidth);
- // First allocate Connected Sockets Heap
- if((ConnectHeap = HeapCreate(0, sizeof(SOCKDATA) * 5, sizeof(SOCKDATA) * 100)) == NULL)
- {
- // ERROR - abort
- return 0;
- }
- if(((LPVOID)ConnectedSockets = HeapAlloc(ConnectHeap,0, sizeof(SOCKDATA) * 5)) == NULL)
- {
- // ERROR - abort
- return 0;
- }
- NextFree = 0; // First available SOCKDATA struct
- MaxConnects = 5; // Allocate only 5 structures at a time
- // Load winsock dll
- wVersionRequested = MAKEWORD(1, 1);
- if (WSAStartup(wVersionRequested, &wsaData) != 0)
- {
- // ERROR -abort
- return 0;
- }
- // Determine size of buffer needed
- if (EnumProtocols(NULL, NULL, &sizeProtBuf) != SOCKET_ERROR)
- {
- // ERROR
- return 0;
- }
- // Allocate buffer of appropriate size
- if (((LPVOID)lpProtBuf = VirtualAlloc(NULL,
- sizeProtBuf,
- MEM_COMMIT,
- PAGE_READWRITE)) == NULL)
- {
- // ERROR
- return 0;
- }
- // Do the real EnumProtocols call--note that there is no GETNEXT mechanism here.
- // We have to allocate a single buffer big enough to hold everything.
- if ((cNumProt = EnumProtocols(NULL, lpProtBuf, &sizeProtBuf)) == SOCKET_ERROR)
- {
- // ERROR
- return 0;
- }
- // Now that we know how many protocols we have, allocate array of globchat
- // SOCKDATA structures to hold info on each.
- if (((LPVOID)ServerSockets = VirtualAlloc(NULL,
- cNumProt * sizeof(SOCKDATA),
- MEM_COMMIT,
- PAGE_READWRITE)) == NULL)
- {
- // ERROR
- return 0;
- }
- // Walk through available protocols, j is index to list of all protocols, k is index to list of
- // protocols we can use.
- for (j = 0, k = 0; j < cNumProt; j++)
- {
- // Only want connection oriented protocols
- if((lpProtBuf[j].dwServiceFlags & XP_CONNECTIONLESS) == 0)
- {
- // Attempt to setup listen and fill in SOCKDATA struct
- if (MakeServSock(hwnd, &ServerSockets[k], &lpProtBuf[j]))
- {
- // Successfully using protocol...add it to our list box
- wsprintf(outtext, "%st%d", ServerSockets[k].lpProtocolName, ServerSockets[k].currconnects);
- SendMessage(hwndProtocolList, LB_ADDSTRING, 0, (LPARAM)&outtext);
- // Found a good protocol!
- GoodProts[k++] = j;
- }
- }
- }
- cNumProt = k; // Number of good protocols
- // Register with Name Spaces
- // In the future this will be done transparently, but for now must do it
- // manually for specific protocols. The only NSPs we have are DNS and SAP.
- // Since DNS is static, that just leaves us with SAP to do.
- if((SAPSocket = socket(AF_IPX, // IPX family
- SOCK_DGRAM, // SAPs are broadcasted
- NSPROTO_IPX + 4) // Uses IPX packet type 4
- ) != INVALID_SOCKET)
- {
- // Find IPX address which we are bound to
- for(k = 0;k < cNumProt; k++)
- {
- if(ServerSockets[k].protocol == NSPROTO_SPXII)
- {
- // Initialize SAP data
- SAPData.operation = 0x200; // 2 = SAP response(network order)
- SAPData.servicetype = 0x5607; // 0756 Assigned by Novell specifically for GLOBCHAT only!!!!
- strcpy(SAPData.name, "GLOBCHAT"); // My service name
- memcpy((void *)SAPData.network, // Copy address into SAP body
- (void *)(ServerSockets[k].addr.sa_data),
- 12);
- SAPData.hops = 0; // Hop count starts at zero
- SAPSockAddr.sa_family = AF_IPX; // SAP packets sent over IPX
- AtoH((char *)&SAPSockAddr.sa_socket, "0452", 2); // SAP destination socket address is 0452.
- // Bind to SAP socket
- if (bind(SAPSocket, (PSOCKADDR) &SAPSockAddr, sizeof(SOCKADDR_IPX)) == SOCKET_ERROR)
- {
- // Error binding to SAP socket
- return 0;
- }
- else
- {
- // build destination address for SAP's IPX header (broadcast)
- SAPDestSockAddr.sa_family = AF_IPX;
- AtoH("00000000",SAPDestSockAddr.sa_netnum, 4);
- AtoH("FFFFFFFFFFFF", SAPDestSockAddr.sa_nodenum, 6);
- AtoH("0452", (char *)&SAPDestSockAddr.sa_socket, 2);
- // Setup socket to allow broadcasts
- bcaststat = TRUE;
- addrlen = sizeof(bcaststat);
- setsockopt(SAPSocket, SOL_SOCKET, SO_BROADCAST, (char *)&bcaststat, sizeof(bcaststat));
- sendto(SAPSocket, (char *)&SAPData, sizeof(SAPData), MSG_DONTROUTE, (struct sockaddr *)&SAPDestSockAddr, sizeof(SAPDestSockAddr));
- // Set timer to remind us to send SAP packet every 60 seconds.
- SetTimer(hwnd, SAPTIMER, 60000, NULL);
- }
- break;
- }
- }
- }
- return 0;
- }
- //
- // FUNCTION: MsgSize(HWND, UINT, WPARAM, LPARAM)
- //
- // PURPOSE: Resizes child listboxes to fit nicely within parent
- //
- // PARAMETERS:
- //
- // hwnd - Window handle
- // uMessage - Message number (Unused)
- // wparam - Extra data (Unused)
- // lparam - Window dimensions
- //
- // RETURN VALUE:
- //
- // Always returns 0 - Message handled
- //
- // COMMENTS:
- //
- //
- LRESULT MsgSize(HWND hwnd, UINT uMessage, WPARAM wparam, LPARAM lparam)
- {
- MoveWindow(hwndProtocolList,
- 1, (HIWORD(lparam) / 4),
- (LOWORD(lparam) / 2),
- (HIWORD(lparam) * 3) / 4,
- TRUE);
- MoveWindow(hwndClientList,
- LOWORD(lparam) /2,
- HIWORD(lparam) / 4,
- LOWORD(lparam) / 2,
- (HIWORD(lparam) * 3) / 4,
- TRUE);
- return 0;
- }
- //
- // FUNCTION: MsgTimer(HWND, UINT, WPARAM, LPARAM)
- //
- // PURPOSE: Sends out SAP packet every 60 seconds
- //
- // PARAMETERS:
- //
- // hwnd - Window handle
- // uMessage - Message number (Unused)
- // wparam - Should be = SAPTIMER
- // lparam - Extra data (Unused)
- //
- // RETURN VALUE:
- //
- // Always returns 0 - Message handled
- //
- // COMMENTS:
- //
- //
- LRESULT MsgTimer(HWND hwnd, UINT uMessage, WPARAM wparam, LPARAM lparam)
- {
- sendto(SAPSocket, (char *) &SAPData, sizeof(SAPData), MSG_DONTROUTE, (struct sockaddr *)&SAPDestSockAddr, sizeof(SAPDestSockAddr));
- return 0;
- }
- //
- // FUNCTION: MsgConnected(HWND, UINT, WPARAM, LPARAM)
- //
- // PURPOSE: Handles new connection notifications
- //
- // PARAMETERS:
- //
- // hwnd - Window handle
- // uMessage - Message number (Unused)
- // wparam - socket which has the connection
- // lparam - loword = event, hiword = error code
- //
- // RETURN VALUE:
- //
- // Always returns 0 - Message handled
- //
- // COMMENTS:
- //
- //
- LRESULT MsgConnected(HWND hwnd, UINT uMessage, WPARAM wparam, LPARAM lparam)
- {
- int k, addrlen;
- int index;
- char outtext[80];
- // May have to increase our heap size
- if(NextFree >= MaxConnects)
- {
- if(HeapAlloc(ConnectHeap, 0, sizeof(SOCKDATA) * 5) == NULL)
- {
- // ERROR on heap allocation...don't accept new connections
- return 0;
- }
- MaxConnects += 5; // We've got five more connect entries available
- }
- // find socket that connect is refering to
- k = 0;
- while(ServerSockets[k].sock != wparam) k++;
- // Lets keep track of our progress
- ServerSockets[k].status = SOCKSTAT_ACCEPTING;
- // Some address our bigger than a sockaddr struct. I threw in some reserved bytes to cover it.
- addrlen = sizeof(ConnectedSockets[NextFree].addr) + sizeof(ConnectedSockets[NextFree].reserved);
- // Accept the connect request
- if ((ConnectedSockets[NextFree].sock = accept(ServerSockets[k].sock,
- &ConnectedSockets[NextFree].addr,
- &addrlen)) == INVALID_SOCKET)
- {
- // ERROR clean up ConnectedSockets (that is don't increment NextFree) and go on our way
- return 0;
- }
- if(WSAAsyncSelect(ConnectedSockets[NextFree].sock, hwnd, MW_DATAREADY, FD_READ | FD_CLOSE) == SOCKET_ERROR)
- {
- // ERROR clean up connection
- closesocket(ConnectedSockets[NextFree].sock);
- return 0;
- }
- // Fill in SOCKDATA structure for client socket
- ConnectedSockets[NextFree].protocol = ServerSockets[k].protocol;
- ConnectedSockets[NextFree].type = ServerSockets[k].type;
- ConnectedSockets[NextFree].servsockindex = k;
- ConnectedSockets[NextFree++].status = SOCKSTAT_CONNECTED;
- // Increment protocol connection count and display
- ServerSockets[k].currconnects ++;
- index = SendMessage(hwndProtocolList, LB_FINDSTRING, (WPARAM)-1, (LPARAM)ServerSockets[k].lpProtocolName);
- SendMessage(hwndProtocolList, LB_DELETESTRING, index, 0);
- wsprintf(outtext, "%st%d", ServerSockets[k].lpProtocolName, ServerSockets[k].currconnects);
- SendMessage(hwndProtocolList, LB_ADDSTRING, 0, (LPARAM)&outtext);
- // Don't forget to set server socket status back to listening
- ServerSockets[k].status = SOCKSTAT_LISTENING;
- return 0;
- }
- //
- // FUNCTION: MsgDataready(HWND, UINT, WPARAM, LPARAM)
- //
- // PURPOSE: Handles incoming socket data notifications and close socket
- // notifications
- //
- // PARAMETERS:
- //
- // hwnd - Window handle
- // uMessage - Message number
- // wparam - socket which has the data
- // lparam - loword = event, hiword = error code
- //
- // RETURN VALUE:
- //
- // Always returns 0 - Message handled
- //
- // COMMENTS:
- //
- //
- LRESULT MsgDataready(HWND hwnd, UINT uMessage, WPARAM wparam, LPARAM lparam)
- {
- int k, j, l;
- int totalbytesread;
- int index;
- char outtext[80];
- // Find the appropriate socket...allow for the reuse of a closed socket handle
- for (k = 0; k < NextFree; k++)
- {
- if((ConnectedSockets[k].sock == wparam) && (ConnectedSockets[k].status != SOCKSTAT_CLOSED))
- break;
- }
- if(LOWORD(lparam) == FD_CLOSE)
- {
- // Socket closed notification--cleanup!
- closesocket(ConnectedSockets[k].sock);
- // Delete name from client list display
- UpdateClientList(ConnectedSockets[k].name, SOCKSTAT_CLOSED, NULL);
- // Take name off of other clients' available list
- if (ConnectedSockets[k].status == SOCKSTAT_AVAILABLE)
- {
- deregistername(ConnectedSockets[k].name);
- }
- // if this connection was in session with another peer...notify peer of disconnect
- // First, find peer
- for (j = 0; j < NextFree; j++)
- {
- if((ConnectedSockets[j].sock == ConnectedSockets[k].peer) &&
- (ConnectedSockets[j].status == SOCKSTAT_INSESSION))
- {
- break;
- }
- }
- if (j < NextFree) // Did we find a peer?
- {
- // Yes, build message header
- xferbuf.hdr.signature = MYSIGNATURE;
- xferbuf.hdr.length = totalbytesread = HDRSIZE;
- xferbuf.hdr.command = SESSION_CLOSE;
- // Send session close message
- senddatamessage(ConnectedSockets[j].sock, &xferbuf);
- // Update Peer's displayed status
- ConnectedSockets[j].status = SOCKSTAT_AVAILABLE;
- UpdateClientList(ConnectedSockets[j].name, SOCKSTAT_AVAILABLE, NULL);
- // Propagate the fact that the peer is now available for other chats
- // and give peer list of other available clients
- for (l = 0; l < NextFree; l++)
- {
- if ((l != j) && (ConnectedSockets[l].status == SOCKSTAT_AVAILABLE))
- {
- xferbuf.hdr.command = REGISTER_NAME;
- lstrcpy(xferbuf.data, ConnectedSockets[l].name);
- xferbuf.hdr.length = REALLEN(ConnectedSockets[l].name) + HDRSIZE;
- senddatamessage(ConnectedSockets[j].sock, &xferbuf);
- lstrcpy(xferbuf.data, ConnectedSockets[j].name);
- xferbuf.hdr.length = REALLEN(ConnectedSockets[j].name) + HDRSIZE;
- senddatamessage(ConnectedSockets[l].sock, &xferbuf);
- }
- }
- }
- // Cleanup ConnectedSockets array
- ConnectedSockets[k].status = SOCKSTAT_CLOSED;
- j = ConnectedSockets[k].servsockindex;
- // Fix protocol connection count display
- ServerSockets[j].currconnects --;
- index = SendMessage(hwndProtocolList, LB_FINDSTRING, (WPARAM)-1, (LPARAM)ServerSockets[j].lpProtocolName);
- SendMessage(hwndProtocolList, LB_DELETESTRING, index, 0);
- wsprintf(outtext, "%st%d", ServerSockets[j].lpProtocolName, ServerSockets[j].currconnects);
- SendMessage(hwndProtocolList, LB_ADDSTRING, 0, (LPARAM)&outtext);
- return 0;
- }
- // There's data to read...read it!
- if(!recvdatamessage(&ConnectedSockets[k], &xferbuf))
- {
- return 0;
- }
- // We've got our whole message! Now switch() on the command flag
- switch(xferbuf.hdr.command)
- {
- case REGISTER_NAME: // First message we should receive on a connection
- if(ConnectedSockets[k].status != SOCKSTAT_CONNECTED)
- {
- // ERROR -- we weren't expecting this...drop it
- return 0;
- }
- // Get name and add to internal structs and display
- lstrcpy(ConnectedSockets[k].name, xferbuf.data);
- ConnectedSockets[k].status = SOCKSTAT_AVAILABLE;
- UpdateClientList(ConnectedSockets[k].name, SOCKSTAT_AVAILABLE, NULL);
- // Send notification to other "AVAILABLE" sockets that we have a new peer available
- for (j = 0; j < NextFree; j++)
- {
- if((j != k) && (ConnectedSockets[j].status == SOCKSTAT_AVAILABLE))
- {
- // message in xferbuf should be able to be sent just like it is
- senddatamessage(ConnectedSockets[j].sock, &xferbuf);
- }
- }
- // Send notifications back to registering peer of all the currently available peers
- for (j = 0; j < NextFree; j++)
- {
- if((j != k) && (ConnectedSockets[j].status == SOCKSTAT_AVAILABLE))
- {
- // found one...build message and send it
- xferbuf.hdr.signature = MYSIGNATURE;
- xferbuf.hdr.length = REALLEN(ConnectedSockets[j].name) + HDRSIZE;
- xferbuf.hdr.command = REGISTER_NAME;
- lstrcpy(xferbuf.data, ConnectedSockets[j].name);
- senddatamessage(ConnectedSockets[k].sock, &xferbuf);
- }
- }
- return 0;
- case XFER_DATA: // For passing data between two insession peers
- if(ConnectedSockets[k].status != SOCKSTAT_INSESSION)
- {
- // ERROR -- we weren't expecting this...drop data
- return 0;
- }
- // forward the message to peer...should be able transfer
- // message without modification
- senddatamessage(ConnectedSockets[k].peer, &xferbuf);
- return 0;
- case REQUEST_SESSION: // Client is asking another peer for a chat
- if(ConnectedSockets[k].status != SOCKSTAT_AVAILABLE)
- {
- // ERROR -- we weren't expecting this...drop data
- return 0;
- }
- ConnectedSockets[k].status = SOCKSTAT_REQSESSION;
- UpdateClientList(ConnectedSockets[k].name, SOCKSTAT_REQSESSION, xferbuf.data);
- // Find the socket which corresponds to the name
- for(j = 0; j < NextFree; j++)
- {
- if(lstrcmp(ConnectedSockets[j].name, xferbuf.data) == 0)
- {
- if(ConnectedSockets[j].status == SOCKSTAT_AVAILABLE)
- {
- // Found It!
- break;
- }
- }
- }
- if (j == NextFree) return 0;
- // Copy requester's name into send data buffer
- lstrcpy(xferbuf.data, ConnectedSockets[k].name);
- xferbuf.hdr.length = HDRSIZE + REALLEN(ConnectedSockets[k].name);
- senddatamessage(ConnectedSockets[j].sock, &xferbuf);
- // Update connected sockets structures
- ConnectedSockets[j].status = SOCKSTAT_REQSESSION;
- UpdateClientList(ConnectedSockets[j].name, SOCKSTAT_REQSESSION, ConnectedSockets[k].name);
- ConnectedSockets[j].peer = ConnectedSockets[k].sock;
- ConnectedSockets[k].peer = ConnectedSockets[j].sock;
- return 0;
- case SESSION_REQUEST_RESPONSE: // Response to session request
- if(ConnectedSockets[k].status != SOCKSTAT_REQSESSION)
- {
- // ERROR -- not expecting this...drop packet
- return 0;
- }
- // find peer entry
- for (j = 0; j < NextFree; j++)
- {
- if ((ConnectedSockets[j].sock == ConnectedSockets[k].peer) &&
- (ConnectedSockets[j].status == SOCKSTAT_REQSESSION))
- {
- // Found it!
- break;
- }
- }
- if (j == NextFree)
- {
- // ERROR -- couldn't find peer...drop packet
- return 0;
- }
- // forward response to requester
- senddatamessage(ConnectedSockets[k].peer, &xferbuf);
- if(*(xferbuf.data) == 1)
- {
- // Session accepted, change status of sockets
- ConnectedSockets[k].status = SOCKSTAT_INSESSION;
- ConnectedSockets[j].status = SOCKSTAT_INSESSION;
- UpdateClientList(ConnectedSockets[k].name, SOCKSTAT_INSESSION, ConnectedSockets[j].name);
- UpdateClientList(ConnectedSockets[j].name, SOCKSTAT_INSESSION, ConnectedSockets[k].name);
- deregistername(ConnectedSockets[k].name);
- deregistername(ConnectedSockets[j].name);
- }
- else
- {
- // Session not accepted, make sockets available
- ConnectedSockets[k].status = SOCKSTAT_AVAILABLE;
- ConnectedSockets[j].status = SOCKSTAT_AVAILABLE;
- UpdateClientList(ConnectedSockets[k].name, SOCKSTAT_AVAILABLE, NULL);
- UpdateClientList(ConnectedSockets[j].name, SOCKSTAT_AVAILABLE, NULL);
- }
- return 0;
- case SESSION_CLOSE: // Insession client chose "End Chat" option
- if (ConnectedSockets[k].status != SOCKSTAT_INSESSION)
- {
- // We weren't expecting this...drop packet
- return 0;
- }
- // Find Peer
- for (j = 0; j < NextFree; j++)
- {
- if((ConnectedSockets[j].sock == ConnectedSockets[k].peer) &&
- (ConnectedSockets[j].status == SOCKSTAT_INSESSION))
- {
- // Found it
- break;
- }
- }
- if(j == NextFree)
- {
- // ERROR - couldn't find peer...drop message
- return 0;
- }
- // forward message
- senddatamessage(ConnectedSockets[k].peer,&xferbuf);
- // Change Status
- ConnectedSockets[k].status = SOCKSTAT_AVAILABLE;
- ConnectedSockets[j].status = SOCKSTAT_AVAILABLE;
- UpdateClientList(ConnectedSockets[k].name, SOCKSTAT_AVAILABLE, NULL);
- UpdateClientList(ConnectedSockets[j].name, SOCKSTAT_AVAILABLE, NULL);
- // register names of both peers with other available clients. Also
- // provide current available client names to both peers
- for (l = 0; l < NextFree; l++) // l = index to all connected sockets
- // k = index of current peer
- // j = index of socket who generated message
- {
- if (ConnectedSockets[l].status == SOCKSTAT_AVAILABLE)
- {
- if ( l != k)
- {
- xferbuf.hdr.signature = MYSIGNATURE;
- xferbuf.hdr.length = REALLEN(ConnectedSockets[k].name) + HDRSIZE;
- xferbuf.hdr.command = REGISTER_NAME;
- lstrcpy(xferbuf.data, ConnectedSockets[k].name);
- senddatamessage(ConnectedSockets[l].sock, &xferbuf);
- if (l != j)
- {
- xferbuf.hdr.length = REALLEN(ConnectedSockets[l].name) + HDRSIZE;
- lstrcpy(xferbuf.data, ConnectedSockets[l].name);
- senddatamessage(ConnectedSockets[k].sock, &xferbuf);
- }
- }
- if (l != j)
- {
- xferbuf.hdr.signature = MYSIGNATURE;
- xferbuf.hdr.length = REALLEN(ConnectedSockets[j].name) + HDRSIZE;
- xferbuf.hdr.command = REGISTER_NAME;
- lstrcpy(xferbuf.data, ConnectedSockets[j].name);
- senddatamessage(ConnectedSockets[l].sock, &xferbuf);
- if (l != k)
- {
- xferbuf.hdr.length = REALLEN(ConnectedSockets[l].name) + HDRSIZE;
- lstrcpy(xferbuf.data, ConnectedSockets[l].name);
- senddatamessage(ConnectedSockets[j].sock, &xferbuf);
- }
- }
- }
- }
- return 0;
- } // End message command switch
- // ERROR -- If we get here, we had an invalid message... drop it
- return 0;
- }
- //
- // FUNCTION: MsgCommand(HWND, UINT, WPARAM, LPARAM)
- //
- // PURPOSE: Handle the WM_COMMAND messages for the main window.
- //
- // PARAMETERS:
- // hwnd - window handle
- // uMessage - WM_COMMAND (Unused)
- // GET_WM_COMMAND_ID(wparam, lparam) - Command identifier
- // GET_WM_COMMAND_HWND(wparam, lparam) - Control handle
- //
- // RETURN VALUE:
- // The return value depends on the message number. If the message
- // is implemented in the message dispatch table, the return value is
- // the value returned by the message handling function. Otherwise,
- // the return value is the value returned by the default window procedure.
- //
- // COMMENTS:
- // Call the DispCommand() function with the main window's command dispatch
- // information (cmdiMain) and the command specific information.
- //
- LRESULT MsgCommand(HWND hwnd, UINT uMessage, WPARAM wparam, LPARAM lparam)
- {
- return DispCommand(&cmdiMain, hwnd, wparam, lparam);
- }
- //
- // FUNCTION: MsgDestroy(HWND, UINT, WPARAM, LPARAM)
- //
- // PURPOSE: Calls PostQuitMessage().
- //
- // PARAMETERS:
- //
- // hwnd - Window handle (Unused)
- // uMessage - Message number (Unused)
- // wparam - Extra data (Unused)
- // lparam - Extra data (Unused)
- //
- // RETURN VALUE:
- //
- // Always returns 0 - Message handled
- //
- // COMMENTS:
- //
- //
- LRESULT MsgDestroy(HWND hwnd, UINT uMessage, WPARAM wparam, LPARAM lparam)
- {
- PostQuitMessage(0);
- return 0;
- }
- //
- // FUNCTION: CmdExit(HWND, WORD, WORD, HWND)
- //
- // PURPOSE: Exit the application.
- //
- // PARAMETERS:
- // hwnd - The window.
- // wCommand - IDM_EXIT (unused)
- // wNotify - Notification number (unused)
- // hwndCtrl - NULL (unused)
- //
- // RETURN VALUE:
- // Always returns 0 - command handled.
- //
- // COMMENTS:
- //
- //
- LRESULT CmdExit(HWND hwnd, WORD wCommand, WORD wNotify, HWND hwndCtrl)
- {
- DestroyWindow(hwnd);
- return 0;
- }