OWLNext    7.0
Borland's Object Windows Library for the modern age
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
wsksockd.cpp
Go to the documentation of this file.
1//----------------------------------------------------------------------------
2// ObjectWindows
3// Copyright (c) 1995, 1996 by Borland International, All Rights Reserved
4//
5/// \file
6/// Winsock for OWL subsystem.
7/// Based on work by Paul Pedriana, 70541.3223@compuserve.com
8//----------------------------------------------------------------------------
9#include <owl/pch.h>
10#include <owl/defs.h>
11#include <owl/winsock.h>
12
13namespace owl {
14
16
17//
18/// Actually 512 is the absolute guaranteed minimum value. The WSAData
19/// structure has the actual value (>=512).
20//
22
23//
24/// This function does nothing. It relies on TSocket to do all the work.
25//
31
32//
33/// This function does nothing. It relies on TSocket to do all the work.
34//
40
41//
42/// This function does nothing. It relies on TSocket to do all the work.
43//
50
51//
52/// This function reads the chars into the chData buffer, and removes the data from
53/// the queue. chData is a pointer to a destination buffer for the data.
54/// nCharsToRead should be set to the maximum desired read size, which needs to be
55/// equal or less to the size of chData.
56/// The sAddress parameter is filled with the address of the sender. It returns
57/// WINSOCK_ERROR if there was an error, WINSOCK_NOERROR otherwise. This Read will
58/// get the data from the next buffered packet and delete the packet from memory
59/// when finished. Thus if this function is called with a nCharsToRead that is
60/// smaller than the next packet, only part of the packet will be read and the rest
61/// will be lost.
62/// Upon return, nCharsToRead is set to the actual number of characters read. If
63/// nCharsToRead returns 0, no data was read. If the function return value is
64/// WINSOCK_ERROR, there was a Windows Sockets error. Otherwise, the call was
65/// successful, even though no data may have been read.
66//
68{
69 // Simply call recvfrom() and return if some kind of error is encountered.
70 //
71 int addressSize = sizeof(sockaddr);
72 ///PP Need to change this to allow flags.
75
77 // It is entirely possible to get a blocking error here. For example, a
78 // call to recv() could have been made right after the message was
79 // posted by the driver, but before this notification function got called.
80 //
81 charsToRead = 0; // This will be available for the caller to examine.
84 return WINSOCK_NOERROR; // This is not considered an "error" under Winsock.
85 // Some other error occurred, return from this function.
86 //
87 return WINSOCK_ERROR;
88 }
90 return WINSOCK_NOERROR;
91}
92
93//
94/// This function puts the data in the queue and attempts to write the first item in
95/// the queue. At the end of the function, an attempt to write the queue is made. If
96/// it fails, the data is sent later, after the system has given notification that
97/// it is ready. This function returns WINSOCK_ERROR or WINSOCK_NOERROR.
98//
100 bool /*becomeOwnerOfData*/, bool /*copyData*/)
101{
102 // Note that bBecomeOwnerOfdata and bCopyData are ignored if we are using DataQueues.
103 // Note that thus function may block here if blocking is enabled.
104 //
105 ///PP need to enable flags use.
107 &outSocketAddress, sizeof(sockaddr));
108 if (charsSent == SOCKET_ERROR) {
109 //It is entirely possible to get a blocking error here. For example, a call to
110 // send() could have been made right after the message was posted by the driver,
111 // but before this notification function got called.
112 //
113 charsToWrite = 0;
116 return WINSOCK_NOERROR;
117 return WINSOCK_ERROR;
118 }
120 return WINSOCK_NOERROR;
121}
122
123//
124/// Simply calls the other Write() function with the latest address. Arguments and
125/// return values are the same.
126//
128{
129 return Write(data, charsToWrite, PeerSocketAddress, becomeOwnerOfData, copyData);
130}
131
132//
133/// This function is called whenever the socket receives a read notification. This
134/// means that data on the port is ready to be read. This function doesn't do much
135/// with the error parameter. It simply doesn't do the read if there is an error
136/// value. According to Winsock documentation, this error may be "any error in winsock.h".
137//
139{
140 if (error) {
141 LastError = error; // TWinSockDll::WSAGetLastError();
142 return WINSOCK_ERROR;
143 }
144
145 // This function dan't do anything on its own without data queues. Without
146 // DataQueues, you can do two things: 1) subclass TDatagramSocket and write
147 // your own DoReadNotification() or 2) Have the socket redirect the FD_READ
148 // notification to the window of your choice with Socket::SetNotificationSet()
149 // and SetNotificationWindow().
150 //
151 return WINSOCK_NOERROR;
152}
153
154//
155/// This function is called whenever the socket receives a write notification.
156//
158{
159 if (error) {
160 LastError = error; // TWinSockDll::WSAGetLastError();
161 return WINSOCK_ERROR;
162 }
163
164 // This function dan't do anything on its own without data queues. Without
165 // DataQueues, you can do two things: 1) subclass TDatagramSocket and write
166 // your own DoWriteNotification() or 2) Have the socket redirect the FD_WRITE
167 // notification to the window of your choice with Socket::SetNotificationSet()
168 // and SetNotificationWindow().
169 //
170 return WINSOCK_NOERROR;
171}
172
173//----------------------------------------------------------------------------
174
175//
176/// This function calls TSocket constructor and initializes the state of the
177/// connection to not connected.
178//
180:
181 TSocket(),
182 ConnectStatus(NotConnected)
183{
184}
185
186//
187/// This function is an alias constructor.
188//
190:
191 TSocket(src)
192{
193 ///!PP Important: Unless there is a way I haven't found yet, you can't tell
194 // what the ConnectStatus is, given just a SOCKET descriptor.
195 // Needs to be set somehow:
196 // nConnectStatus = ???;
197}
198
199//
200// Constructor for a protocol defined by an int.
201//
208
209//
210/// This function copies the socket connection information.
211//
213{
215 return *this;
216}
217
218//
219/// This reads from the already received and queued data. This data has already been
220/// received from the socket driver.
221//
223{
224 // Try to receive the characters.
225 //
226 int charsReceived = TWinSockDll::recv(Handle, data, charsToRead, 0); ///PP I Need to allow the use of flags here.
228 // It is entirely possible to get a blocking error here. For example, a call to
229 // recv() could have been made right after the message was posted by the driver,
230 // but before this notification function got called.
231 //
232 charsToRead = 0; // This will be available for the caller to examine.
235 return WINSOCK_NOERROR;
236 // Some other error occurred.
237 //
238 return WINSOCK_ERROR;
239 }
241 return WINSOCK_NOERROR;
242}
243
244//
245/// This function writes the buffer into the stream.
246//
247int TStreamSocket::Write(char* data, int& charsToWrite, int flags,
248 bool /*becomeOwnerOfData*/, bool /*copyData*/)
249{
250 int charsSent = TWinSockDll::send(Handle, data, charsToWrite, flags);
251 if (charsSent == SOCKET_ERROR) {
252 // It is entirely possible to get a blocking error here. For example, a call to
253 // send() could have been made right after the message was posted by the driver,
254 // but before this notification function got called.
255 //
256 charsToWrite = 0;
258 if (LastError == WSAEWOULDBLOCK) {
259 return WINSOCK_NOERROR;
260 }
261 return WINSOCK_ERROR;
262 }
264 return WINSOCK_NOERROR;
265}
266
267//
268/// This function works just like the Read() function, but it works on the OOB
269/// queue.
270//
272{
273 // Try to receive the characters.
274 ///PP I Need to allow the use of flags here.
275 //
278 // It is entirely possible to get a blocking error here. For example, a call to
279 // recv() could have been made right after the message was posted by the driver,
280 // but before this notification function got called.
281 //
282 charsToRead = 0;
285 return WINSOCK_NOERROR;
286 // Some other error occurred.
287 return WINSOCK_ERROR;
288 }
290 return WINSOCK_NOERROR;
291}
292
293//
294/// Works just like TStreamSocket::Write(), except it adds in the MSG_OOB into the
295/// flags.
296///
297/// Perform write operation using out-of-band data (i.e. via a logically
298/// independent tranmission channel between the connected sockets).
299/// \note For 'non urgent data', you may used TStreamSocket::Write() instead.
300//
301int TStreamSocket::WriteOOB(char* data, int& charsToWrite, int flags,
302 bool /*becomeOwnerOfData*/, bool /*copyData*/)
303{
304 flags |= MSG_OOB;
305 int charsSent = TWinSockDll::send(Handle, data, charsToWrite, flags);
306 if (charsSent == SOCKET_ERROR) {
307 // It is entirely possible to get a blocking error here. For example, a call to
308 // send() could have been made right after the message was posted by the driver,
309 // but before this notification function got called.
310 //
311 charsToWrite = 0;
313 if (LastError == WSAEWOULDBLOCK) {
314 return WINSOCK_NOERROR;
315 }
316 return WINSOCK_ERROR;
317 }
319 return WINSOCK_NOERROR;
320}
321
322//
323/// This function puts this socket into a passive "listening" mode.
324//
334
335//
336/// This function sets myPeerSocketAddress to sAddressToConnectTo then calls
337/// Connect(). (See Connect() for more details.)
338//
344
345//
346/// This function uses myPeerSocketAddress, which needs to be set before calling
347/// this function. The connection attempt (and this function) should return right
348/// away, without blocking. When actually connected, a notification comes from the
349/// driver at the DoConnectNotification() function. Upon receiving that
350/// notification, the nConnectStatus is set to nConnected. Technically, a datagram
351/// socket can call connect; doing this sets the default address for future
352/// send()/recv() calls that the datagram socket might use. It's in the
353/// TStreamSocket class for simplicity, and because the TDatagramSocket class
354/// already supports its own default address system.
355//
357{
358 if (TWinSockDll::connect(Handle, &PeerSocketAddress, sizeof(sockaddr))) {
360 return WINSOCK_ERROR;
361 }
362 // The following code assumes that the socket is in non-blocking mode. If the socket was in
363 // blocking mode, then nConnectStatus would be nConnected. Thus, this code is slightly
364 // bugged and can be patched with a call to select() to determine whether the socket is
365 // really connected or not. Looked at another way, a blocking socket can be said to be
366 // connected if nConnectStatus is either nConnected or nConnectPending.
367 //
369 return WINSOCK_NOERROR;
370}
371
372//
373/// This function will try to accept a connection with the first connecting peer
374/// that is waiting in the queue. If successful, the TStreamSocket& socket will have
375/// a valid and connected socket, a proper status of nConnected, and the correct
376/// peer socket address. The caller usually calls this function in response to an
377/// Accept notification. The caller merely needs to create a new TStreamSocket and
378/// pass it to this function. The default constructor for TStreamSocket can be used,
379/// because this function fixes up the missing parts.
380//
382{
383 if (Accept(socket.Handle, socket.PeerSocketAddress) == WINSOCK_NOERROR) {
384 socket.ConnectStatus = Connected;
385 socket.SetSocketStyle(Family, Type, Protocol); //Copy our Family, etc. just to make sure.
386 return WINSOCK_NOERROR;
387 }
388 return WINSOCK_ERROR;
389}
390
391//
392/// This function tries to accept a connection with the first connecting peer that
393/// is waiting in the queue. If successful, the socket reference argument is set to
394/// a new connected socket. The sAddress reference argument is set to the address of
395/// the connecting peer. The caller of this function may immediately use the new
396/// socket with data sends, etc.
397///
398/// Note that the caller may want to flag the socket as connected. If the socket
399/// belongs to a StreamSocket, its nConnectionStatus can be set as nConnected. The
400/// return value is either WINSOCK_ERROR or WINSOCK_NOERROR. If there is an error,
401/// then nLastError will be set with the appropriate error.
402///
403/// Note that this call could be made when no pending socket connections are in the
404/// queue. If this is the case, the call will block if the socket is marked as
405/// blocking, and will return WINSOCK_ERROR with WSAEWOULDBLOCK if the socket is
406/// marked as non-blocking. This function is usually called in response to an accept
407/// notification. A socket is set up as a stream socket and listen() is called. When
408/// a connection is ready, the driver notifies the listening socket with a
409/// DoAcceptNotification() call. (See the DoAcceptNotification() call
410/// documentation.) This Accept() function should be called as a result.
411//
412int TStreamSocket::Accept(SOCKET& socket, sockaddr& address)
413{
414 int addressLength = sizeof(sockaddr);
415 socket = TWinSockDll::accept(Handle, &address, &addressLength);
416
417 if (socket == static_cast<SOCKET>(INVALID_SOCKET)) {
419 return WINSOCK_ERROR;
420 }
421 return WINSOCK_NOERROR;
422}
423
424//
425/// This function is called when the socket receives a read notification unless
426/// there is an error. This means that data on the port is ready to be read.
427/// This function doesn't do much with the nError parameter. It doesn't do the read
428/// if there is an error value.
429//
431{
432 if (error) {
433 LastError = error; // TWinSockDll::WSAGetLastError();
434 return WINSOCK_ERROR;
435 }
436 return WINSOCK_NOERROR;
437}
438
439//
440/// This function is called when the socket receives a write notification. This
441/// means that data on the port is ready to be written.
442//
444{
445 if (error) {
446 LastError = error; ///PP TWinSockDll::WSAGetLastError();
447 return WINSOCK_ERROR;
448 }
449
450 // This function dan't do anything on its own without data queues. Without
451 // DataQueues, you can do two things: 1) subclass TStreamSocket and write
452 // your own DoWriteNotification() or 2) Have the socket redirect the FD_WRITE
453 // notification to the window of your choice with Socket::SetNotificationSet()
454 // and SetNotificationWindow().
455 //
456 return WINSOCK_NOERROR;
457}
458
459//
460/// This notification appears when OOB data is ready to be received on the socket
461/// port.
462//
464{
465 if (error) {
466 LastError = error; // TWinSockDll::WSAGetLastError();
467 return WINSOCK_ERROR;
468 }
469
470 // This function dan't do anything on its own without data queues. Without
471 // DataQueues, you can do two things: 1) subclass TStreamSocket and write
472 // your own DoOOBNotification() or 2) Have the socket redirect the FD_OOB
473 // notification to the window of your choice with Socket::SetNotificationSet()
474 // and SetNotificationWindow().
475 //
476 return WINSOCK_NOERROR;
477}
478
479//
480/// This notification occurs when a client socket on the network is attempting to
481/// connect to you. Code needs to be written to intercept this notification.
482//
483int TStreamSocket::DoAcceptNotification(const SOCKET& /*s*/, int /*error*/)
484{
485 return 0; // We don't do anything. We let the pending acceptance sit there.
486}
487
488//
489/// This means that the connection attempted with a server on the network has
490/// completed. This function gets called sometime after this object makes a
491/// connect() attempt. If the connect attempt was non-blocking, a notification is
492/// posted. When this function gets called, the nConnectStatus should be
493/// nConnecting.
494//
496{
497 if (error) {
498 // There was an error, and we cannot connect; this may due to a number of reasons.
499 // We turn off our 'nConnectStatus' to 'nNotConnected'. This is becuase our attempt
500 // to connect failed.
501 //
503 LastError = error; ///PP TWinSockDll::WSAGetLastError();
504 return WINSOCK_ERROR;
505 }
507 return WINSOCK_NOERROR;
508}
509
510//
511/// This notification gets called when the socket has been closed. The socket is
512/// marked as not connected, so the user can find out about it. It is important to
513/// read any data that may be waiting in the queue before changing the status of the
514/// connection and doing any notification.
515//
517{
518 if (error) {
519 LastError = error; ///PP TWinSockDll::WSAGetLastError();
520 return WINSOCK_ERROR;
521 }
522 return WINSOCK_NOERROR;
523}
524
525} // OWL namespace
526/* ========================================================================== */
527
static int MaxPacketSendSize
Defined by the WSAStartup() call return information (WSAData).
Definition wsksockd.h:55
TDatagramSocket()
This function does nothing. It relies on TSocket to do all the work.
Definition wsksockd.cpp:26
int Read(char *data, int &charsToRead, TSocketAddress &sAddress)
This function reads the chars into the chData buffer, and removes the data from the queue.
Definition wsksockd.cpp:67
int DoReadNotification(const SOCKET &s, int error)
This function is called whenever the socket receives a read notification.
Definition wsksockd.cpp:138
int Write(char *data, int &charsToWrite, TSocketAddress &outSocketAddress, bool becomeOwnerOfData=true, bool copyData=true)
This function puts the data in the queue and attempts to write the first item in the queue.
Definition wsksockd.cpp:99
int DoWriteNotification(const SOCKET &s, int error)
This function is called whenever the socket receives a write notification.
Definition wsksockd.cpp:157
The TSocketAddress class stores a Winsock socket address.
Definition wskaddr.h:38
TSocket encapsulates the basic attributes of a socket.
Definition wsksock.h:102
int LastError
Last Error.
Definition wsksock.h:206
TSocket & operator=(TSocket &newSocket)
Definition wsksock.cpp:120
int Protocol
IPPROTO_TCP, etc.
Definition wsksock.h:205
int Type
SOCK_STREAM, etc.
Definition wsksock.h:204
int Family
PF_INET, etc. (this is the protocol family)
Definition wsksock.h:203
virtual void SetSocketStyle(int nNewFamily=PF_INET, int nNewType=SOCK_STREAM, int nNewProtocol=0)
The SetSocketStyle function can be used to set or change some TSocket member data.
Definition wsksock.cpp:232
virtual void SetPeerSocketAddress(TSocketAddress &newPeerSocketAddress)
The 'myPeerSocketAddress' member variable is useful for Datagram sockets because it allows them to sp...
Definition wsksock.cpp:403
The TStreamSocket encapsulates a Winsock stream socket.
Definition wsksockd.h:76
int Read(char *data, int &charsToRead)
This reads from the already received and queued data.
Definition wsksockd.cpp:222
int Write(char *data, int &charsToWrite, int flags=0, bool becomeOwnerOfData=true, bool copyData=true)
This function writes the buffer into the stream.
Definition wsksockd.cpp:247
int DoOOBNotification(const SOCKET &s, int nError)
This notification appears when OOB data is ready to be received on the socket port.
Definition wsksockd.cpp:463
int Connect()
This function uses myPeerSocketAddress, which needs to be set before calling this function.
Definition wsksockd.cpp:356
int DoReadNotification(const SOCKET &s, int nError)
This function is called when the socket receives a read notification unless there is an error.
Definition wsksockd.cpp:430
TStreamSocket()
This function calls TSocket constructor and initializes the state of the connection to not connected.
Definition wsksockd.cpp:179
int DoCloseNotification(const SOCKET &s, int nError)
This notification gets called when the socket has been closed.
Definition wsksockd.cpp:516
int DoAcceptNotification(const SOCKET &s, int nError)
This notification occurs when a client socket on the network is attempting to connect to you.
Definition wsksockd.cpp:483
@ ConnectPending
Connection is pending.
Definition wsksockd.h:82
@ Connected
Currently connected.
Definition wsksockd.h:83
@ NotConnected
This socket is not used.
Definition wsksockd.h:81
@ Listening
Waiting for a connection.
Definition wsksockd.h:84
int WriteOOB(char *data, int &charsToWrite, int nFlags=MSG_OOB, bool becomeOwnerOfData=true, bool copyData=true)
Works just like TStreamSocket::Write(), except it adds in the MSG_OOB into the flags.
Definition wsksockd.cpp:301
TStreamSocket & operator=(TStreamSocket &src)
This function copies the socket connection information.
Definition wsksockd.cpp:212
int ReadOOB(char *data, int &charsToRead)
This function works just like the Read() function, but it works on the OOB queue.
Definition wsksockd.cpp:271
int DoWriteNotification(const SOCKET &s, int nError)
This function is called when the socket receives a write notification.
Definition wsksockd.cpp:443
int Listen(int nMaxQueuedConnections=N_DEF_MAX_QUEUED_CONNECTIONS)
This function puts this socket into a passive "listening" mode.
Definition wsksockd.cpp:325
int Accept(TStreamSocket &socket)
This function will try to accept a connection with the first connecting peer that is waiting in the q...
Definition wsksockd.cpp:381
int DoConnectNotification(const SOCKET &s, int nError)
This means that the connection attempted with a server on the network has completed.
Definition wsksockd.cpp:495
enum owl::TStreamSocket::TConnectStatus ConnectStatus
static int sendto(SOCKET s, LPCSTR buf, int len, int flags, const struct sockaddr *to, int toLen)
Definition winsock.cpp:178
static int listen(SOCKET s, int backlog)
Definition winsock.cpp:124
static int WSAGetLastError(void)
Definition winsock.cpp:294
static SOCKET accept(SOCKET s, struct sockaddr *addr, int *addrLen)
Definition winsock.cpp:33
static int connect(SOCKET s, struct sockaddr *name, int nameLen)
Definition winsock.cpp:56
static int send(SOCKET s, LPCSTR buf, int len, int flags)
Definition winsock.cpp:171
static int recvfrom(SOCKET s, char *buf, int len, int flags, struct sockaddr *from, int *fromLen)
Definition winsock.cpp:152
static int recv(SOCKET s, char *buf, int len, int flags)
Definition winsock.cpp:145
Object Windows Library (OWLNext Core)
Definition animctrl.h:22
OWL_DIAGINFO
Definition animctrl.cpp:14
General definitions used by all ObjectWindows programs.
Main header of the Winsock OWL subsystem.
#define WINSOCK_NOERROR
Definition wskhostm.h:30
#define WINSOCK_ERROR
Definition wskhostm.h:31