OWLNext    7.0
Borland's Object Windows Library for the modern age
Loading...
Searching...
No Matches
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