c++.windows.32-bits - 32 bit dll compiling part 2
- Janne Naukkarinen (954/954) Jan 14 2004 This is 32-bit DLL compiling.
- Walter (6/867) Jan 18 2004 EXETYPE WINDOWS
This is 32-bit DLL compiling. From kiviapaja hotmail.com Why next example fails? dmc -mn -WD ../gwinsock.cpp -w -D__DMC__ -Dgwinsock_main kernel32.lib user32.lib gdi32.lib comdlg32.lib wsock32.lib > err2.txt link gwinsock,,,kernel32+user32+gdi32+comdlg32+wsock32,gwinsock/noi; OPTLINK (R) for Win32 Release 7.50B1 Copyright (C) Digital Mars 1989 - 2001 All Rights Reserved OPTLINK : Warning 148: USE16/USE32 Mismatch : DGROUP F:\DM\BIN\..\lib\SNN.lib(dllstart) Error 83: Illegal frame on start address OPTLINK : Warning 174: 32-bit Segments Inappropriate for 16-bit Segmented output gwinsock.obj(gwinsock) Error 116: NEAR call to IMPORT at Relative 00025H from Segment _TEXT FRAME = Frame of Group FLAT 0000 TARGET = External Symbol _WSAStartup 8 00000H FIXUPP Type = 32-bit Conditional JMP --- errorlevel 2 Is this from source code or .def My def is like this: LIBRARY gwinsock DESCRIPTION 'GWinSock -- socket wrapper dll' EXETYPE WINDOWS EXPORTS _gensock_close 1 _gensock_connect 2 _gensock_getchar 3 _gensock_gethostname 4 _gensock_put_data 5 _gensock_put_data_buffered 6 _gensock_put_data_flush 7 My source is like this ------- gwinsock.cpp ------------ // -*- C++ -*- // generic socket DLL, winsock version // disclaimer: a C programmer wrote this. // $Id: gensock.cpp 1.151 2004/12/25 22:07:10 NooN Exp $ // $Id: gensock.cpp 1.15 1994/11/23 22:38:10 rushing Exp $ #include <windows.h> #include <string.h> #include <ctype.h> extern "C" { #include <winsock.h> #include "gwinsock.h" } #ifdef _DEBUG #ifndef __BORLANDC__ #define _CRTDBG_MAP_ALLOC #include <stdlib.h> #include <crtdbg.h> #else #include <stdlib.h> #endif #else #include <stdlib.h> #endif //MDS increased buffer from 512 19991214 #define SOCKET_BUFFER_SIZE 1500 // This is for NT HANDLE dll_module_handle; #define GET_CURRENT_TASK dll_module_handle #define TASK_HANDLE_TYPE HANDLE // // ------------------------------------------------------------------------- -- // container for a buffered SOCK_STREAM. class connection { private: SOCKET the_socket; char * in_buffer; char * out_buffer; unsigned int in_index; unsigned int out_index; unsigned int in_buffer_total; unsigned int out_buffer_total; unsigned int last_winsock_error; TASK_HANDLE_TYPE owner_task; fd_set fds; struct timeval timeout; public: connection (void); ~connection (void); int get_connected (char far * hostname, char far * service); SOCKET get_socket(void) { return (the_socket); } TASK_HANDLE_TYPE get_owner_task(void) { return (owner_task); } int get_buffer(int wait); int close (void); int getchar (int wait, char far * ch); int put_data (char far * data, unsigned long length); int put_data_buffered (char far* data, unsigned long length); int put_data_flush (void); }; // //----------------------------------------------------------------------- ---- // we keep lists of connections in this class class connection_list { private: connection * data; connection_list * next; public: connection_list (void); ~connection_list (void); void push (connection & conn); // should really use pointer-to-memberfun for these connection * find (SOCKET sock); int how_many_are_mine (void); void remove (socktag sock); }; connection_list global_socket_list; int network_initialized; //int init_winsock (void); //void deinit_winsock (void); // // // #ifdef _DEBUG void complain (char * message) { OutputDebugString (message); } #else void complain (char * message) { MessageBox (NULL, message, "GWINSOCK.DLL Error", MB_OK|MB_ICONHAND); } #endif //----------------------------------------------------------------------- ---- // // int init_winsock(void) { int retval; WSADATA winsock_data; WORD version_required = 0x0101; // Version 1.1 retval = WSAStartup (version_required, &winsock_data); switch (retval) { case 0: // successful break; case WSASYSNOTREADY: return (ERR_SYS_NOT_READY); break; case WSAEINVAL: return (ERR_EINVAL); break; case WSAVERNOTSUPPORTED: return (ERR_VER_NOT_SUPPORTED); break; } network_initialized = 1; return (0); } void deinit_winsock(void) { network_initialized = 0; WSACleanup(); } connection::connection (void) { the_socket = 0; in_index = 0; out_index = 0; in_buffer_total = 0; out_buffer_total = 0; in_buffer = 0; in_buffer = new char[SOCKET_BUFFER_SIZE]; out_buffer = new char[SOCKET_BUFFER_SIZE]; last_winsock_error = 0; } connection::~connection (void) { delete [] in_buffer; // NooN delete [] out_buffer; // NooN ^^ } int gensock_is_a_number (char far* string) { while (*string) { if (!isdigit (*string)) { return (0); } string++; } return (1); } // // ------------------------------------------------------------------------- -- // int connection::get_connected (char FAR * hostname, char FAR * service) { struct hostent FAR * hostentry; struct servent FAR * serventry; unsigned long ip_address; struct sockaddr_in sa_in; int our_port; int nott = 0; int retval, err_code; unsigned long ioctl_blocking = 1; char message[512]; // if the ctor couldn't get a buffer if (!in_buffer || !out_buffer) return (ERR_CANT_MALLOC); // -------------------------------------------------- // resolve the service name // // If they've specified a number, just use it. if (gensock_is_a_number (service)) { char far* tail; our_port = (int) strtol (service, &tail, 10); if (tail == service) { return (ERR_CANT_RESOLVE_SERVICE); } else { our_port = htons (our_port); } } else { // we have a name, we must resolve it. serventry = getservbyname (service, (LPSTR)"tcp"); if (serventry) our_port = serventry->s_port; else { retval = WSAGetLastError(); // Chicago beta is throwing a WSANO_RECOVERY here... if ((retval == WSANO_DATA) || (retval == WSANO_RECOVERY)) { return (ERR_CANT_RESOLVE_SERVICE); } else { return (retval - 5000); } } } // -------------------------------------------------- // resolve the hostname/ipaddress // if ((ip_address = inet_addr (hostname)) != INADDR_NONE) { sa_in.sin_addr.s_addr = ip_address; } else { if ((hostentry = gethostbyname(hostname)) == NULL) { return (ERR_CANT_RESOLVE_HOSTNAME); } sa_in.sin_addr.s_addr = *(long far *)hostentry->h_addr; #if 0 { OutputDebugString(inet_ntoa(sa_in.sin_addr)); } #endif } // -------------------------------------------------- // get a socket // if ((the_socket = socket(AF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET) { return (ERR_CANT_GET_SOCKET); } sa_in.sin_family = AF_INET; sa_in.sin_port = our_port; // set socket options. DONTLINGER will give us a more graceful disconnect // MDS yes, and also terminate our connections before the last command // has been completely sent causing abnormal terminations on the receiving // side! // From www.lcg.org/sock-faq // "... SO_LINGER seems to be required to guarantee delivery of all data." //20000410 #if 0 setsockopt(the_socket,SOL_SOCKET,SO_DONTLINGER,(char *) ¬t, sizeof(nott)); #endif // get a connection if ((retval = connect (the_socket, (struct sockaddr *)&sa_in, sizeof(struct sockaddr_in))==SOCKET_ERROR)) { switch ((err_code = WSAGetLastError())) { // twiddle our thumbs until the connect succeeds case WSAEWOULDBLOCK: break; case WSAECONNREFUSED: return (ERR_CONNECTION_REFUSED); break; default: wsprintf(message, "unexpected error %d from winsock\n", err_code); complain(message); return (ERR_CANT_CONNECT); break; } } owner_task = GET_CURRENT_TASK; // Make this a non-blocking socket ioctlsocket (the_socket, FIONBIO, &ioctl_blocking); // make the FD_SET and timeout structures for later operations... FD_ZERO (&fds); FD_SET (the_socket, &fds); // normal timeout, can be changed by the wait option. timeout.tv_sec = 30; timeout.tv_usec = 0; return (0); } // //----------------------------------------------------------------------- ---- // // The 'wait' parameter, if set, says to return WAIT_A_BIT // if there's no data waiting to be read. int connection::get_buffer(int wait) { int retval; int bytes_read = 0; unsigned long ready_to_read = 0; // Use select to see if data is waiting... FD_ZERO (&fds); FD_SET (the_socket, &fds); // if wait is set, we are polling, return immediately if (wait) { timeout.tv_sec = 0; } else { timeout.tv_sec = 30; } if ((retval = select (0, &fds, NULL, NULL, &timeout)) == SOCKET_ERROR) { char what_error[256]; int error_code = WSAGetLastError(); if (error_code == WSAEINPROGRESS && wait) { return (WAIT_A_BIT); } wsprintf (what_error, "connection::get_buffer() unexpected error from select: %d", error_code); complain (what_error); } // if we don't want to wait if (!retval && wait) { return (WAIT_A_BIT); } // we have data waiting... bytes_read = recv (the_socket,in_buffer,SOCKET_BUFFER_SIZE,0); // just in case. if (bytes_read == 0) { // connection terminated (semi-) gracefully by the other side return (ERR_NOT_CONNECTED); } if (bytes_read == SOCKET_ERROR) { char what_error[256]; int ws_error = WSAGetLastError(); switch (ws_error) { // all these indicate loss of connection (are there more?) case WSAENOTCONN: case WSAENETDOWN: case WSAENETUNREACH: case WSAENETRESET: case WSAECONNABORTED: case WSAECONNRESET: return (ERR_NOT_CONNECTED); break; case WSAEWOULDBLOCK: return (WAIT_A_BIT); break; default: wsprintf (what_error, "connection::get_buffer() unexpected error: %d", ws_error); complain (what_error); } } // reset buffer indices. in_buffer_total = bytes_read; in_index = 0; return (0); } // //----------------------------------------------------------------------- ---- // get a character from this connection. // int connection::getchar(int wait, char FAR * ch) { int retval; if (in_index >= in_buffer_total) { if ((retval = get_buffer(wait))) return (retval); } *ch = in_buffer[in_index++]; return (0); } // //----------------------------------------------------------------------- ---- // FIXME: should try to handle the fact that send can only take // an int, not an unsigned long. int connection::put_data (char far* data, unsigned long length) { int num_sent; int retval; FD_ZERO (&fds); FD_SET (the_socket, &fds); timeout.tv_sec = 30; while (length > 0) { if ((retval = select (0, NULL, &fds, NULL, &timeout)) == SOCKET_ERROR) { char what_error[256]; int error_code = WSAGetLastError(); wsprintf (what_error, "connection::put_data() unexpected error from select: %d", error_code); complain (what_error); } num_sent = send (the_socket, data, length > 1024 ? 1024 : (int)length, 0); if (num_sent == SOCKET_ERROR) { char what_error[256]; int ws_error = WSAGetLastError(); switch (ws_error) { // this is the only error we really expect to see. case WSAENOTCONN: return (ERR_NOT_CONNECTED); break; // seems that we can still get a block case WSAEWOULDBLOCK: case WSAEINPROGRESS: break; default: wsprintf (what_error, "connection::put_data() unexpected error from send(): %d", ws_error); complain (what_error); return (ERR_SENDING_DATA); } } else { length -= num_sent; data += num_sent; } } return (0); } // // // buffered output // int connection::put_data_buffered (char far* data, unsigned long length) { unsigned int sorta_sent = 0; int retval; while (length) { if ((out_index + length) < SOCKET_BUFFER_SIZE) { // we won't overflow, simply copy into the buffer memcpy (out_buffer + out_index, data, (size_t) length); out_index += (unsigned int) length; length = 0; } else { unsigned int orphaned_chunk = SOCKET_BUFFER_SIZE - out_index; // we will overflow, handle it memcpy (out_buffer + out_index, data, orphaned_chunk); // send this buffer... if ((retval = put_data (out_buffer, SOCKET_BUFFER_SIZE))) { return (retval); } length -= orphaned_chunk; out_index = 0; data += orphaned_chunk; } } return (0); } int connection::put_data_flush (void) { int retval; if ((retval = put_data (out_buffer, out_index))) return (retval); else out_index = 0; return(0); } // //----------------------------------------------------------------------- ---- // int connection::close (void) { if (closesocket(the_socket) == SOCKET_ERROR) return (ERR_CLOSING); else return (0); } connection_list::connection_list (void) { next = 0; } connection_list::~connection_list(void) { delete data; } // add a new connection to the list void connection_list::push (connection & conn) { connection_list * new_conn; new_conn = new connection_list(); new_conn->data = data; new_conn->next = next; data = &conn; next = new_conn; } int connection_list::how_many_are_mine(void) { TASK_HANDLE_TYPE current_task = GET_CURRENT_TASK; connection_list * iter = this; int num = 0; while (iter->data) { if (iter->data->get_owner_task() == current_task) num++; iter = iter->next; } return (num); } // find a particular socket's connection object. connection * connection_list::find (SOCKET sock) { connection_list * iter = this; while (iter->data) { if (iter->data->get_socket() == sock) return (iter->data); iter = iter->next; } return (0); } void connection_list::remove (socktag sock) { // at the end if (!data) return; // we can assume next is valid because // the last node is always {0,0} if (data == sock) { delete data; data = next->data; next = next->next; // 8^) return; } // recurse next->remove(sock); } // // ------------------------------------------------------------------------- -- // global variables (shared by all DLL users) // //----------------------------------------------------------------------- ---- // extern "C" { INT WINAPI DllMain (HANDLE hInst, ULONG reason_called,LPVOID reserved) { switch (reason_called) { case DLL_PROCESS_ATTACH: // init dll_module_handle = hInst; break; case DLL_THREAD_ATTACH: break; case DLL_THREAD_DETACH: break; case DLL_PROCESS_DETACH: break; default: break; } return (1); } // ------------------------------------------------------------------------- -- // C/DLL interface // int GENSOCK_EXPORT CELLBACK gensock_connect (char FAR * hostname, char FAR * service, socktag FAR * pst) { int retval; connection * conn = new connection; if (!conn) return (ERR_INITIALIZING); // if this task hasn't opened any sockets yet, then // call WSAStartup() if (global_socket_list.how_many_are_mine() < 1) init_winsock(); global_socket_list.push(*conn); if ((retval = conn->get_connected (hostname, service))) { gensock_close(conn); *pst = 0; return (retval); } *pst = (void FAR *) conn; return (0); } // // // int GENSOCK_EXPORT CELLBACK gensock_getchar (socktag st, int wait, char FAR * ch) { connection * conn; int retval = 0; conn = (connection *) st; if (!conn) return (ERR_NOT_A_SOCKET); if ((retval = conn->getchar(wait, ch))) return (retval); else return (0); } //----------------------------------------------------------------------- ---- // // int GENSOCK_EXPORT CELLBACK gensock_put_data (socktag st, char FAR * data, unsigned long length) { connection * conn; int retval = 0; conn = (connection *) st; if (!conn) return (ERR_NOT_A_SOCKET); if ((retval = conn->put_data(data, length))) return (retval); return (0); } //----------------------------------------------------------------------- ---- // // int GENSOCK_EXPORT CELLBACK gensock_put_data_buffered (socktag st, char FAR * data, unsigned long length) { connection * conn; int retval = 0; conn = (connection *) st; if (!conn) return (ERR_NOT_A_SOCKET); if ((retval = conn->put_data_buffered (data, length))) return (retval); return (0); } //----------------------------------------------------------------------- ---- // // int GENSOCK_EXPORT CELLBACK gensock_put_data_flush (socktag st) { connection * conn; int retval = 0; conn = (connection *) st; if (!conn) return (ERR_NOT_A_SOCKET); if ((retval = conn->put_data_flush() )) return (retval); return (0); } //----------------------------------------------------------------------- ---- // // int GENSOCK_EXPORT CELLBACK gensock_gethostname (char FAR * name, int namelen) { int retval; if ((retval = gethostname(name, namelen))) { return (retval - 5000); } else return (0); } int GENSOCK_EXPORT CELLBACK gensock_close (socktag st) { connection * conn; int retval; conn = (connection *) st; if (!conn) return (ERR_NOT_A_SOCKET); if ((retval = conn->close())) return (retval); global_socket_list.remove((connection *)st); if (global_socket_list.how_many_are_mine() < 1) { deinit_winsock(); } return (0); } } // extern "C" ---------gwinsock.cpp------------ ---------- gwinsock.h------------ and gwinsock.h /* $Id: gensock.h 1.81 2004/12/25 22:06:11 NooN Exp $ */ /* $Id: gensock.h 1.8 1995/01/25 23:28:11 rushing Exp $ */ #define ERR_CANT_MALLOC 4001 #define ERR_SENDING_DATA 4002 #define ERR_INITIALIZING 4003 #define ERR_VER_NOT_SUPPORTED 4004 #define ERR_EINVAL 4005 #define ERR_SYS_NOT_READY 4006 #define ERR_CANT_RESOLVE_HOSTNAME 4007 #define ERR_CANT_GET_SOCKET 4008 #define ERR_READING_SOCKET 4009 #define ERR_NOT_A_SOCKET 4010 #define ERR_BUSY 4011 #define ERR_CLOSING 4012 #define WAIT_A_BIT 4013 #define ERR_CANT_RESOLVE_SERVICE 4014 #define ERR_CANT_CONNECT 4015 #define ERR_NOT_CONNECTED 4016 #define ERR_CONNECTION_REFUSED 4017 #define ERR_NO_ERROR_CODE -5000 /* this is returned by misbehaving stacks that * fail, but don't set an error code */ typedef void * socktag; // #ifdef __BORLANDC__ #ifdef __BC45__ #define CELLBACK CALLBACK #define GENSOCK_EXPORT __export #endif #ifdef __BC55__ #define CELLBACK CALLBACK #define GENSOCK_EXPORT __export #endif #ifdef __BC600__ #define CELLBACK CALLBACK #define CELLBACK CALLBACK #define GENSOCK_EXPORT __export /* #ifdef gwinsock_main #define GENSOCK_EXPORT __declspec(dllexport) #else #define GENSOCK_EXPORT __declspec(dllimport) #endif */ #endif // #endif // borlandc #ifdef __DMC__ #define CELLBACK #ifdef gwinsock_main #define GENSOCK_EXPORT __declspec(dllexport) #else #define GENSOCK_EXPORT __declspec(dllimport) #endif #endif #ifdef __WATCOM__ #define CELLBACK CALLBACK #ifdef gwinsock_main #define GENSOCK_EXPORT __declspec(dllexport) #else #define GENSOCK_EXPORT __declspec(dllimport) #endif #endif #ifdef __GCC__ #define CELLBACK #ifdef gwinsock_main #define GENSOCK_EXPORT __declspec(dllexport) #else #define GENSOCK_EXPORT __declspec(dllimport) #endif #endif #ifdef __MSVC__ #define CELLBACK CALLBACK #ifdef gwinsock_main #define GENSOCK_EXPORT __declspec(dllexport) #else #define GENSOCK_EXPORT __declspec(dllimport) #endif //#define GENSOCK_EXPORT FAR PASCAL #endif #ifdef __cplusplus extern "C" { #endif /* function prototypes */ int GENSOCK_EXPORT CELLBACK gensock_connect (char * hostname, char * service, socktag * pst); int GENSOCK_EXPORT CELLBACK gensock_getchar (socktag st, int wait, char * ch); int GENSOCK_EXPORT CELLBACK gensock_put_data (socktag st, char * data, unsigned long length); int GENSOCK_EXPORT CELLBACK gensock_close (socktag st); int GENSOCK_EXPORT CELLBACK gensock_gethostname (char * name, int namelen); int GENSOCK_EXPORT CELLBACK gensock_put_data_buffered (socktag st, char * data, unsigned long length); int GENSOCK_EXPORT CELLBACK gensock_put_data_flush (socktag st); #ifdef __cplusplus } #endif ------------------- gwinsock.h ------------- Can someone help this? Janne Naukkarinen kiviapaja hotmail.com
Jan 14 2004
EXETYPE WINDOWS specifies a 16 bit output. Use EXETYPE NT instead. See www.digitalmars.com/ctg/ctgDefFiles.html "Janne Naukkarinen" <kiviapaja hotmail.com> wrote in message news:bu4bkg$299g$1 digitaldaemon.com...This is 32-bit DLL compiling. From kiviapaja hotmail.com Why next example fails? dmc -mn -WD ../gwinsock.cpp -w -D__DMC__ -Dgwinsock_main kernel32.lib user32.lib gdi32.lib comdlg32.lib wsock32.lib > err2.txt link gwinsock,,,kernel32+user32+gdi32+comdlg32+wsock32,gwinsock/noi; OPTLINK (R) for Win32 Release 7.50B1 Copyright (C) Digital Mars 1989 - 2001 All Rights Reserved OPTLINK : Warning 148: USE16/USE32 Mismatch : DGROUP F:\DM\BIN\..\lib\SNN.lib(dllstart) Error 83: Illegal frame on start address OPTLINK : Warning 174: 32-bit Segments Inappropriate for 16-bit Segmented output gwinsock.obj(gwinsock) Error 116: NEAR call to IMPORT at Relative 00025H from Segment _TEXT FRAME = Frame of Group FLAT 0000 TARGET = External Symbol _WSAStartup 8 00000H FIXUPP Type = 32-bit Conditional JMP --- errorlevel 2 Is this from source code or .def My def is like this: LIBRARY gwinsock DESCRIPTION 'GWinSock -- socket wrapper dll' EXETYPE WINDOWS EXPORTS _gensock_close 1 _gensock_connect 2 _gensock_getchar 3 _gensock_gethostname 4 _gensock_put_data 5 _gensock_put_data_buffered 6 _gensock_put_data_flush 7 My source is like this ------- gwinsock.cpp ------------ // -*- C++ -*- // generic socket DLL, winsock version // disclaimer: a C programmer wrote this. // $Id: gensock.cpp 1.151 2004/12/25 22:07:10 NooN Exp $ // $Id: gensock.cpp 1.15 1994/11/23 22:38:10 rushing Exp $ #include <windows.h> #include <string.h> #include <ctype.h> extern "C" { #include <winsock.h> #include "gwinsock.h" } #ifdef _DEBUG #ifndef __BORLANDC__ #define _CRTDBG_MAP_ALLOC #include <stdlib.h> #include <crtdbg.h> #else #include <stdlib.h> #endif #else #include <stdlib.h> #endif //MDS increased buffer from 512 19991214 #define SOCKET_BUFFER_SIZE 1500 // This is for NT HANDLE dll_module_handle; #define GET_CURRENT_TASK dll_module_handle #define TASK_HANDLE_TYPE HANDLE // // ------------------------------------------------------------------------- -- // container for a buffered SOCK_STREAM. class connection { private: SOCKET the_socket; char * in_buffer; char * out_buffer; unsigned int in_index; unsigned int out_index; unsigned int in_buffer_total; unsigned int out_buffer_total; unsigned int last_winsock_error; TASK_HANDLE_TYPE owner_task; fd_set fds; struct timeval timeout; public: connection (void); ~connection (void); int get_connected (char far * hostname, char far * service); SOCKET get_socket(void) { return (the_socket); } TASK_HANDLE_TYPE get_owner_task(void) { return (owner_task); } int get_buffer(int wait); int close (void); int getchar (int wait, char far * ch); int put_data (char far * data, unsigned long length); int put_data_buffered (char far* data, unsigned long length); int put_data_flush (void); }; // //----------------------------------------------------------------------- ---- // we keep lists of connections in this class class connection_list { private: connection * data; connection_list * next; public: connection_list (void); ~connection_list (void); void push (connection & conn); // should really use pointer-to-memberfun for these connection * find (SOCKET sock); int how_many_are_mine (void); void remove (socktag sock); }; connection_list global_socket_list; int network_initialized; //int init_winsock (void); //void deinit_winsock (void); // // // #ifdef _DEBUG void complain (char * message) { OutputDebugString (message); } #else void complain (char * message) { MessageBox (NULL, message, "GWINSOCK.DLL Error", MB_OK|MB_ICONHAND); } #endif //----------------------------------------------------------------------- ---- // // int init_winsock(void) { int retval; WSADATA winsock_data; WORD version_required = 0x0101; // Version 1.1 retval = WSAStartup (version_required, &winsock_data); switch (retval) { case 0: // successful break; case WSASYSNOTREADY: return (ERR_SYS_NOT_READY); break; case WSAEINVAL: return (ERR_EINVAL); break; case WSAVERNOTSUPPORTED: return (ERR_VER_NOT_SUPPORTED); break; } network_initialized = 1; return (0); } void deinit_winsock(void) { network_initialized = 0; WSACleanup(); } connection::connection (void) { the_socket = 0; in_index = 0; out_index = 0; in_buffer_total = 0; out_buffer_total = 0; in_buffer = 0; in_buffer = new char[SOCKET_BUFFER_SIZE]; out_buffer = new char[SOCKET_BUFFER_SIZE]; last_winsock_error = 0; } connection::~connection (void) { delete [] in_buffer; // NooN delete [] out_buffer; // NooN ^^ } int gensock_is_a_number (char far* string) { while (*string) { if (!isdigit (*string)) { return (0); } string++; } return (1); } // // ------------------------------------------------------------------------- -- // int connection::get_connected (char FAR * hostname, char FAR * service) { struct hostent FAR * hostentry; struct servent FAR * serventry; unsigned long ip_address; struct sockaddr_in sa_in; int our_port; int nott = 0; int retval, err_code; unsigned long ioctl_blocking = 1; char message[512]; // if the ctor couldn't get a buffer if (!in_buffer || !out_buffer) return (ERR_CANT_MALLOC); // -------------------------------------------------- // resolve the service name // // If they've specified a number, just use it. if (gensock_is_a_number (service)) { char far* tail; our_port = (int) strtol (service, &tail, 10); if (tail == service) { return (ERR_CANT_RESOLVE_SERVICE); } else { our_port = htons (our_port); } } else { // we have a name, we must resolve it. serventry = getservbyname (service, (LPSTR)"tcp"); if (serventry) our_port = serventry->s_port; else { retval = WSAGetLastError(); // Chicago beta is throwing a WSANO_RECOVERY here... if ((retval == WSANO_DATA) || (retval == WSANO_RECOVERY)) { return (ERR_CANT_RESOLVE_SERVICE); } else { return (retval - 5000); } } } // -------------------------------------------------- // resolve the hostname/ipaddress // if ((ip_address = inet_addr (hostname)) != INADDR_NONE) { sa_in.sin_addr.s_addr = ip_address; } else { if ((hostentry = gethostbyname(hostname)) == NULL) { return (ERR_CANT_RESOLVE_HOSTNAME); } sa_in.sin_addr.s_addr = *(long far *)hostentry->h_addr; #if 0 { OutputDebugString(inet_ntoa(sa_in.sin_addr)); } #endif } // -------------------------------------------------- // get a socket // if ((the_socket = socket(AF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET) { return (ERR_CANT_GET_SOCKET); } sa_in.sin_family = AF_INET; sa_in.sin_port = our_port; // set socket options. DONTLINGER will give us a more graceful disconnect // MDS yes, and also terminate our connections before the last command // has been completely sent causing abnormal terminations on the receiving // side! // From www.lcg.org/sock-faq // "... SO_LINGER seems to be required to guarantee delivery of all data." //20000410 #if 0 setsockopt(the_socket,SOL_SOCKET,SO_DONTLINGER,(char *) ¬t, sizeof(nott)); #endif // get a connection if ((retval = connect (the_socket, (struct sockaddr *)&sa_in, sizeof(struct sockaddr_in))==SOCKET_ERROR)) { switch ((err_code = WSAGetLastError())) { // twiddle our thumbs until the connect succeeds case WSAEWOULDBLOCK: break; case WSAECONNREFUSED: return (ERR_CONNECTION_REFUSED); break; default: wsprintf(message, "unexpected error %d from winsock\n", err_code); complain(message); return (ERR_CANT_CONNECT); break; } } owner_task = GET_CURRENT_TASK; // Make this a non-blocking socket ioctlsocket (the_socket, FIONBIO, &ioctl_blocking); // make the FD_SET and timeout structures for later operations... FD_ZERO (&fds); FD_SET (the_socket, &fds); // normal timeout, can be changed by the wait option. timeout.tv_sec = 30; timeout.tv_usec = 0; return (0); } // //----------------------------------------------------------------------- ---- // // The 'wait' parameter, if set, says to return WAIT_A_BIT // if there's no data waiting to be read. int connection::get_buffer(int wait) { int retval; int bytes_read = 0; unsigned long ready_to_read = 0; // Use select to see if data is waiting... FD_ZERO (&fds); FD_SET (the_socket, &fds); // if wait is set, we are polling, return immediately if (wait) { timeout.tv_sec = 0; } else { timeout.tv_sec = 30; } if ((retval = select (0, &fds, NULL, NULL, &timeout)) == SOCKET_ERROR) { char what_error[256]; int error_code = WSAGetLastError(); if (error_code == WSAEINPROGRESS && wait) { return (WAIT_A_BIT); } wsprintf (what_error, "connection::get_buffer() unexpected error from select: %d", error_code); complain (what_error); } // if we don't want to wait if (!retval && wait) { return (WAIT_A_BIT); } // we have data waiting... bytes_read = recv (the_socket,in_buffer,SOCKET_BUFFER_SIZE,0); // just in case. if (bytes_read == 0) { // connection terminated (semi-) gracefully by the other side return (ERR_NOT_CONNECTED); } if (bytes_read == SOCKET_ERROR) { char what_error[256]; int ws_error = WSAGetLastError(); switch (ws_error) { // all these indicate loss of connection (are there more?) case WSAENOTCONN: case WSAENETDOWN: case WSAENETUNREACH: case WSAENETRESET: case WSAECONNABORTED: case WSAECONNRESET: return (ERR_NOT_CONNECTED); break; case WSAEWOULDBLOCK: return (WAIT_A_BIT); break; default: wsprintf (what_error, "connection::get_buffer() unexpected error: %d", ws_error); complain (what_error); } } // reset buffer indices. in_buffer_total = bytes_read; in_index = 0; return (0); } // //----------------------------------------------------------------------- ---- // get a character from this connection. // int connection::getchar(int wait, char FAR * ch) { int retval; if (in_index >= in_buffer_total) { if ((retval = get_buffer(wait))) return (retval); } *ch = in_buffer[in_index++]; return (0); } // //----------------------------------------------------------------------- ---- // FIXME: should try to handle the fact that send can only take // an int, not an unsigned long. int connection::put_data (char far* data, unsigned long length) { int num_sent; int retval; FD_ZERO (&fds); FD_SET (the_socket, &fds); timeout.tv_sec = 30; while (length > 0) { if ((retval = select (0, NULL, &fds, NULL, &timeout)) == SOCKET_ERROR) { char what_error[256]; int error_code = WSAGetLastError(); wsprintf (what_error, "connection::put_data() unexpected error from select: %d", error_code); complain (what_error); } num_sent = send (the_socket, data, length > 1024 ? 1024 : (int)length, 0); if (num_sent == SOCKET_ERROR) { char what_error[256]; int ws_error = WSAGetLastError(); switch (ws_error) { // this is the only error we really expect to see. case WSAENOTCONN: return (ERR_NOT_CONNECTED); break; // seems that we can still get a block case WSAEWOULDBLOCK: case WSAEINPROGRESS: break; default: wsprintf (what_error, "connection::put_data() unexpected error from send(): %d", ws_error); complain (what_error); return (ERR_SENDING_DATA); } } else { length -= num_sent; data += num_sent; } } return (0); } // // // buffered output // int connection::put_data_buffered (char far* data, unsigned long length) { unsigned int sorta_sent = 0; int retval; while (length) { if ((out_index + length) < SOCKET_BUFFER_SIZE) { // we won't overflow, simply copy into the buffer memcpy (out_buffer + out_index, data, (size_t) length); out_index += (unsigned int) length; length = 0; } else { unsigned int orphaned_chunk = SOCKET_BUFFER_SIZE - out_index; // we will overflow, handle it memcpy (out_buffer + out_index, data, orphaned_chunk); // send this buffer... if ((retval = put_data (out_buffer, SOCKET_BUFFER_SIZE))) { return (retval); } length -= orphaned_chunk; out_index = 0; data += orphaned_chunk; } } return (0); } int connection::put_data_flush (void) { int retval; if ((retval = put_data (out_buffer, out_index))) return (retval); else out_index = 0; return(0); } // //----------------------------------------------------------------------- ---- // int connection::close (void) { if (closesocket(the_socket) == SOCKET_ERROR) return (ERR_CLOSING); else return (0); } connection_list::connection_list (void) { next = 0; } connection_list::~connection_list(void) { delete data; } // add a new connection to the list void connection_list::push (connection & conn) { connection_list * new_conn; new_conn = new connection_list(); new_conn->data = data; new_conn->next = next; data = &conn; next = new_conn; } int connection_list::how_many_are_mine(void) { TASK_HANDLE_TYPE current_task = GET_CURRENT_TASK; connection_list * iter = this; int num = 0; while (iter->data) { if (iter->data->get_owner_task() == current_task) num++; iter = iter->next; } return (num); } // find a particular socket's connection object. connection * connection_list::find (SOCKET sock) { connection_list * iter = this; while (iter->data) { if (iter->data->get_socket() == sock) return (iter->data); iter = iter->next; } return (0); } void connection_list::remove (socktag sock) { // at the end if (!data) return; // we can assume next is valid because // the last node is always {0,0} if (data == sock) { delete data; data = next->data; next = next->next; // 8^) return; } // recurse next->remove(sock); } // // ------------------------------------------------------------------------- -- // global variables (shared by all DLL users) // //----------------------------------------------------------------------- ---- // extern "C" { INT WINAPI DllMain (HANDLE hInst, ULONG reason_called,LPVOID reserved) { switch (reason_called) { case DLL_PROCESS_ATTACH: // init dll_module_handle = hInst; break; case DLL_THREAD_ATTACH: break; case DLL_THREAD_DETACH: break; case DLL_PROCESS_DETACH: break; default: break; } return (1); } // ------------------------------------------------------------------------- -- // C/DLL interface // int GENSOCK_EXPORT CELLBACK gensock_connect (char FAR * hostname, char FAR * service, socktag FAR * pst) { int retval; connection * conn = new connection; if (!conn) return (ERR_INITIALIZING); // if this task hasn't opened any sockets yet, then // call WSAStartup() if (global_socket_list.how_many_are_mine() < 1) init_winsock(); global_socket_list.push(*conn); if ((retval = conn->get_connected (hostname, service))) { gensock_close(conn); *pst = 0; return (retval); } *pst = (void FAR *) conn; return (0); } // // // int GENSOCK_EXPORT CELLBACK gensock_getchar (socktag st, int wait, char FAR * ch) { connection * conn; int retval = 0; conn = (connection *) st; if (!conn) return (ERR_NOT_A_SOCKET); if ((retval = conn->getchar(wait, ch))) return (retval); else return (0); } //----------------------------------------------------------------------- ---- // // int GENSOCK_EXPORT CELLBACK gensock_put_data (socktag st, char FAR * data, unsigned long length) { connection * conn; int retval = 0; conn = (connection *) st; if (!conn) return (ERR_NOT_A_SOCKET); if ((retval = conn->put_data(data, length))) return (retval); return (0); } //----------------------------------------------------------------------- ---- // // int GENSOCK_EXPORT CELLBACK gensock_put_data_buffered (socktag st, char FAR * data, unsigned long length) { connection * conn; int retval = 0; conn = (connection *) st; if (!conn) return (ERR_NOT_A_SOCKET); if ((retval = conn->put_data_buffered (data, length))) return (retval); return (0); } //----------------------------------------------------------------------- ---- // // int GENSOCK_EXPORT CELLBACK gensock_put_data_flush (socktag st) { connection * conn; int retval = 0; conn = (connection *) st; if (!conn) return (ERR_NOT_A_SOCKET); if ((retval = conn->put_data_flush() )) return (retval); return (0); } //----------------------------------------------------------------------- ---- // // int GENSOCK_EXPORT CELLBACK gensock_gethostname (char FAR * name, int namelen) { int retval; if ((retval = gethostname(name, namelen))) { return (retval - 5000); } else return (0); } int GENSOCK_EXPORT CELLBACK gensock_close (socktag st) { connection * conn; int retval; conn = (connection *) st; if (!conn) return (ERR_NOT_A_SOCKET); if ((retval = conn->close())) return (retval); global_socket_list.remove((connection *)st); if (global_socket_list.how_many_are_mine() < 1) { deinit_winsock(); } return (0); } } // extern "C" ---------gwinsock.cpp------------ ---------- gwinsock.h------------ and gwinsock.h /* $Id: gensock.h 1.81 2004/12/25 22:06:11 NooN Exp $ */ /* $Id: gensock.h 1.8 1995/01/25 23:28:11 rushing Exp $ */ #define ERR_CANT_MALLOC 4001 #define ERR_SENDING_DATA 4002 #define ERR_INITIALIZING 4003 #define ERR_VER_NOT_SUPPORTED 4004 #define ERR_EINVAL 4005 #define ERR_SYS_NOT_READY 4006 #define ERR_CANT_RESOLVE_HOSTNAME 4007 #define ERR_CANT_GET_SOCKET 4008 #define ERR_READING_SOCKET 4009 #define ERR_NOT_A_SOCKET 4010 #define ERR_BUSY 4011 #define ERR_CLOSING 4012 #define WAIT_A_BIT 4013 #define ERR_CANT_RESOLVE_SERVICE 4014 #define ERR_CANT_CONNECT 4015 #define ERR_NOT_CONNECTED 4016 #define ERR_CONNECTION_REFUSED 4017 #define ERR_NO_ERROR_CODE -5000 /* this is returned by misbehaving stacks that * fail, but don't set an error code */ typedef void * socktag; // #ifdef __BORLANDC__ #ifdef __BC45__ #define CELLBACK CALLBACK #define GENSOCK_EXPORT __export #endif #ifdef __BC55__ #define CELLBACK CALLBACK #define GENSOCK_EXPORT __export #endif #ifdef __BC600__ #define CELLBACK CALLBACK #define CELLBACK CALLBACK #define GENSOCK_EXPORT __export /* #ifdef gwinsock_main #define GENSOCK_EXPORT __declspec(dllexport) #else #define GENSOCK_EXPORT __declspec(dllimport) #endif */ #endif // #endif // borlandc #ifdef __DMC__ #define CELLBACK #ifdef gwinsock_main #define GENSOCK_EXPORT __declspec(dllexport) #else #define GENSOCK_EXPORT __declspec(dllimport) #endif #endif #ifdef __WATCOM__ #define CELLBACK CALLBACK #ifdef gwinsock_main #define GENSOCK_EXPORT __declspec(dllexport) #else #define GENSOCK_EXPORT __declspec(dllimport) #endif #endif #ifdef __GCC__ #define CELLBACK #ifdef gwinsock_main #define GENSOCK_EXPORT __declspec(dllexport) #else #define GENSOCK_EXPORT __declspec(dllimport) #endif #endif #ifdef __MSVC__ #define CELLBACK CALLBACK #ifdef gwinsock_main #define GENSOCK_EXPORT __declspec(dllexport) #else #define GENSOCK_EXPORT __declspec(dllimport) #endif //#define GENSOCK_EXPORT FAR PASCAL #endif #ifdef __cplusplus extern "C" { #endif /* function prototypes */ int GENSOCK_EXPORT CELLBACK gensock_connect (char * hostname, char * service, socktag * pst); int GENSOCK_EXPORT CELLBACK gensock_getchar (socktag st, int wait, char * ch); int GENSOCK_EXPORT CELLBACK gensock_put_data (socktag st, char * data, unsigned long length); int GENSOCK_EXPORT CELLBACK gensock_close (socktag st); int GENSOCK_EXPORT CELLBACK gensock_gethostname (char * name, int namelen); int GENSOCK_EXPORT CELLBACK gensock_put_data_buffered (socktag st, char * data, unsigned long length); int GENSOCK_EXPORT CELLBACK gensock_put_data_flush (socktag st); #ifdef __cplusplus } #endif ------------------- gwinsock.h ------------- Can someone help this? Janne Naukkarinen kiviapaja hotmail.com
Jan 18 2004