January 14, 2004 32 bit dll compiling part 2 | ||||
---|---|---|---|---|
| ||||
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 |
January 19, 2004 Re: 32 bit dll compiling part 2 | ||||
---|---|---|---|---|
| ||||
Posted in reply to Janne Naukkarinen | 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 > |
Copyright © 1999-2021 by the D Language Foundation