Renamed GSocket_SetBlocking to GSocket_SetNonBlocking and *Fallback to *Callback

Added GSocket_SetTimeout
Added timeout support in wxSocket (as it was in previous releases)
Updated documentation


git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@3215 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Guilhem Lavaux 1999-07-30 17:54:18 +00:00
parent aa994705c7
commit 39b91ecabe
14 changed files with 158 additions and 60 deletions

View File

@ -183,6 +183,7 @@
\input slider.tex
\input sckaddr.tex
\input socket.tex
%\input gsocket.tex
\input splitevt.tex
\input strmsock.tex
\input spinbutt.tex

View File

@ -23,10 +23,18 @@
Creates a new input stream on the the specified path. You can use all except the seek
functionality of wxStream. Seek isn't available on all streams. For example,
http or ftp streams doesn't deal with it. Other functions like StreamSize and
Tell aren't available for the moment for this sort of stream.
http or ftp streams doesn't deal with it. Other functions like Tell and SeekI
for this sort of stream.
You will be notified when the EOF is reached by an error.
\wxheading{Note}
You can know the size of the file you are getting using \helpref{wxStreamBase::GetSize()}{wxstreambasegetsize}.
But there is a limitation: as HTTP servers aren't obliged to pass the size ofi
the file, in some case, you will be returned 0xfffffff by GetSize(). In these
cases, you should use the value returned by \helpref{wxInputStream::LastRead()}{wxinputstreamlastread}:
this value will be 0 when the stream is finished.
\wxheading{Return value}
Returns the initialized stream. You will have to delete it yourself once you
@ -48,10 +56,14 @@ It sets data of a field to be sent during the next request to the HTTP server. T
name is specified by \it{header} and the content by \it{h\_data}.
This is a low level function and it assumes that you know what you are doing.
\membersection{wxHTTP::SetHeader}
\membersection{wxHTTP::GetHeader}
\func{wxString}{GetHeader}{\param{const wxString\&}{ header}}
Returns the data attached with a field whose name is specified by \it{header}.
If the field doesn't exist, it will return an empty string and not a NULL string.
\wxheading{Note}
The header is not case-sensitive: I mean that "CONTENT-TYPE" and "content-type"
represent the same header.

View File

@ -32,7 +32,7 @@ Destructor.
Returns the first character in the input queue and removes it.
\membersection{wxInputStream::LastRead}
\membersection{wxInputStream::LastRead}\label{wxinputstreamlastread}
\constfunc{size\_t}{LastRead}{\void}

View File

@ -76,7 +76,7 @@ real position in the stream.
See \helpref{OnSysRead}{wxstreambaseonsysread}.
\membersection{wxStreamBase::GetSize}
\membersection{wxStreamBase::GetSize}\label{wxstreambasegetsize}
\constfunc{size\_t}{GetSize}{\void}

View File

@ -8,7 +8,7 @@
This class is input stream from ZIP archive. The archive
must be local file (accessible via FILE*).
It has all features including StreamSize and seeking.
It has all features including GetSize and seeking.
\wxheading{Derived from}

View File

@ -66,7 +66,7 @@ enum {
typedef int GSocketEventFlags;
typedef void (*GSocketFallback)(GSocket *socket, GSocketEvent event,
typedef void (*GSocketCallback)(GSocket *socket, GSocketEvent event,
char *cdata);
#ifdef __cplusplus
@ -134,13 +134,19 @@ int GSocket_Write(GSocket *socket, const char *buffer,
int size);
bool GSocket_DataAvailable(GSocket *socket);
/* Flags */
/* Flags/Parameters */
/*
GSocket_SetTimeout() sets the timeout for reading and writing IO call. Time
is expressed in milliseconds.
*/
void GSocket_SetTimeout(GSocket *socket, unsigned long millisec);
/*
GSocket_SetBlocking() puts the socket in non-blocking mode. This is useful
if we don't want to wait.
*/
void GSocket_SetBlocking(GSocket *socket, bool block);
void GSocket_SetNonBlocking(GSocket *socket, bool non_block);
/*
GSocket_GetError() returns the last error occured on the socket stream.
@ -161,7 +167,7 @@ GSocketError GSocket_GetError(GSocket *socket);
Server socket -> a client request a connection
LOST: the connection is lost
SetFallback accepts a combination of these flags so a same callback can
SetCallback accepts a combination of these flags so a same callback can
receive different events.
An event is generated only once and its state is reseted when the relative
@ -169,14 +175,14 @@ GSocketError GSocket_GetError(GSocket *socket);
For example: INPUT -> GSocket_Read()
CONNECTION -> GSocket_Accept()
*/
void GSocket_SetFallback(GSocket *socket, GSocketEventFlags event,
GSocketFallback fallback, char *cdata);
void GSocket_SetCallback(GSocket *socket, GSocketEventFlags event,
GSocketCallback fallback, char *cdata);
/*
UnsetFallback will disables all fallbacks specified by "event".
UnsetCallback will disables all fallbacks specified by "event".
NOTE: event may be a combination of flags
*/
void GSocket_UnsetFallback(GSocket *socket, GSocketEventFlags event);
void GSocket_UnsetCallback(GSocket *socket, GSocketEventFlags event);
/* GAddress */

View File

@ -24,15 +24,16 @@
// wxSocket headers (generic)
// ---------------------------------------------------------------------------
#ifdef WXPREC
#include "wx/wxprec.h"
# include <wx/wxprec.h>
#else
#include "wx/event.h"
#include "wx/string.h"
# include <wx/event.h>
# include <wx/string.h>
#endif
#include "wx/sckaddr.h"
#include <wx/sckaddr.h>
#include "wx/gsocket.h"
class WXDLLEXPORT wxTimer;
class WXDLLEXPORT wxSocketEvent;
class WXDLLEXPORT wxSocketBase : public wxEvtHandler
{
@ -65,11 +66,13 @@ protected:
bool m_notify_state; // Notify state
int m_id; // Socket id (for event handler)
// Defering variables
enum {
DEFER_READ, DEFER_WRITE, NO_DEFER
} m_defering; // Defering state
} m_defering; // Defering state
char *m_defer_buffer; // Defering target buffer
size_t m_defer_nbytes; // Defering buffer size
wxTimer *m_defer_timer; // Timer for defering mode
wxList m_states; // Stack of states

View File

@ -128,32 +128,62 @@ bool wxSocketBase::Close()
// --------------------------------------------------------------
// wxSocketBase base IO function
// --------------------------------------------------------------
class _wxSocketInternalTimer: public wxTimer {
public:
int *m_state;
int m_new_val;
void Notify()
{
*m_state = m_new_val; // Change the value
}
};
int wxSocketBase::DeferRead(char *buffer, size_t nbytes)
{
GSocketEventFlags old_event_flags;
bool old_notify_state;
// Timer for timeout
_wxSocketInternalTimer timer;
wxASSERT(m_defering == NO_DEFER);
// Set the defering mode to READ.
m_defering = DEFER_READ;
// Save the old state.
old_event_flags = NeededReq();
old_notify_state = m_notify_state;
// Set the new async flag.
SetNotify(GSOCK_INPUT_FLAG | GSOCK_LOST_FLAG);
Notify(TRUE);
// Set the current buffer.
m_defer_buffer = buffer;
m_defer_nbytes = nbytes;
m_defer_timer = &timer;
timer.m_state = (int *)&m_defer_buffer;
timer.m_new_val = (int)NULL;
timer.Start(m_timeout * 1000, FALSE);
// Wait for buffer completion.
while (m_defer_buffer != NULL)
wxYield();
timer.Stop();
// Restore the old state.
Notify(old_notify_state);
SetNotify(old_event_flags);
// Disable defering mode.
m_defering = NO_DEFER;
m_defer_timer = NULL;
// Return the number of bytes read from the socket.
return nbytes-m_defer_nbytes;
}
@ -272,22 +302,39 @@ int wxSocketBase::DeferWrite(const char *buffer, size_t nbytes)
{
GSocketEventFlags old_event_flags;
bool old_notify_state;
// Timer for timeout
_wxSocketInternalTimer timer;
wxASSERT(m_defering == NO_DEFER);
m_defering = DEFER_WRITE;
// Save the old state
old_event_flags = NeededReq();
old_notify_state = m_notify_state;
SetNotify(GSOCK_OUTPUT_FLAG | GSOCK_LOST_FLAG);
Notify(TRUE);
// Set the current buffer
m_defer_buffer = (char *)buffer;
m_defer_nbytes = nbytes;
// Start timer
timer.m_state = (int *)&m_defer_buffer;
timer.m_new_val = (int)NULL;
m_defer_timer = &timer;
timer.Start(m_timeout * 1000, FALSE);
while (m_defer_buffer != NULL)
wxYield();
// Stop timer
m_defer_timer = NULL;
timer.Stop();
// Restore the old state
Notify(old_notify_state);
SetNotify(old_event_flags);
@ -396,11 +443,15 @@ void wxSocketBase::DoDefer(GSocketEvent req_evt)
if (ret < 0)
m_defer_nbytes++;
// If we are waiting for all bytes to be acquired, keep the defering modei
// enabled.
if ((m_flags & WAITALL) == 0 || m_defer_nbytes == 0 || ret < 0) {
m_defer_buffer = NULL;
Notify(FALSE);
} else
} else {
m_defer_buffer += ret;
m_defer_timer->Start(m_timeout * 1000, FALSE);
}
}
// ---------------------------------------------------------------------
@ -522,16 +573,6 @@ char *wxSocketBase::CallbackData(char *data)
// --------- wxSocketBase wait functions ------------------------
// --------------------------------------------------------------
class _wxSocketInternalTimer: public wxTimer {
public:
int *m_state;
void Notify()
{
*m_state = GSOCK_MAX_EVENT; // Just to say it's a timeout.
}
};
static void wx_socket_wait(GSocket *socket, GSocketEvent event, char *cdata)
{
int *state = (int *)cdata;
@ -542,25 +583,30 @@ static void wx_socket_wait(GSocket *socket, GSocketEvent event, char *cdata)
bool wxSocketBase::_Wait(long seconds, long milliseconds, int type)
{
bool old_notify_state = m_notify_state;
int state = 0;
int state = -1;
_wxSocketInternalTimer timer;
if (!m_connected || !m_socket)
return FALSE;
// Set the variable to change
timer.m_state = &state;
timer.m_new_val = GSOCK_MAX_EVENT;
// Disable the previous handler
Notify(FALSE);
// Set the timeout
timer.Start(seconds * 1000 + milliseconds, TRUE);
GSocket_SetFallback(m_socket, type, wx_socket_wait, (char *)&state);
GSocket_SetCallback(m_socket, type, wx_socket_wait, (char *)&state);
while (state == 0)
while (state == -1)
wxYield();
GSocket_UnsetFallback(m_socket, type);
GSocket_UnsetCallback(m_socket, type);
timer.Stop();
// Notify will restore automatically the old GSocket flags
Notify(old_notify_state);
return (state != GSOCK_MAX_EVENT);
@ -649,12 +695,12 @@ void wxSocketBase::Notify(bool notify)
if (!m_socket)
return;
GSocket_UnsetFallback(m_socket, GSOCK_INPUT_FLAG | GSOCK_OUTPUT_FLAG |
GSocket_UnsetCallback(m_socket, GSOCK_INPUT_FLAG | GSOCK_OUTPUT_FLAG |
GSOCK_LOST_FLAG | GSOCK_CONNECTION_FLAG);
if (!notify)
return;
GSocket_SetFallback(m_socket, m_neededreq, wx_socket_fallback, (char *)this);
GSocket_SetCallback(m_socket, m_neededreq, wx_socket_fallback, (char *)this);
}
void wxSocketBase::OnRequest(GSocketEvent req_evt)

View File

@ -53,7 +53,7 @@ void _GSocket_GUI_Destroy(GSocket *socket)
free(socket->m_gui_dependent);
}
void _GSocket_Install_Fallback(GSocket *socket, GSocketEvent event)
void _GSocket_Install_Callback(GSocket *socket, GSocketEvent event)
{
GdkInputCondition flag;
int c;
@ -76,7 +76,7 @@ void _GSocket_Install_Fallback(GSocket *socket, GSocketEvent event)
_GSocket_GDK_Input, (gpointer)socket);
}
void _GSocket_Uninstall_Fallback(GSocket *socket, GSocketEvent event)
void _GSocket_Uninstall_Callback(GSocket *socket, GSocketEvent event)
{
int c;
gint *m_id;

View File

@ -53,7 +53,7 @@ void _GSocket_GUI_Destroy(GSocket *socket)
free(socket->m_gui_dependent);
}
void _GSocket_Install_Fallback(GSocket *socket, GSocketEvent event)
void _GSocket_Install_Callback(GSocket *socket, GSocketEvent event)
{
GdkInputCondition flag;
int c;
@ -76,7 +76,7 @@ void _GSocket_Install_Fallback(GSocket *socket, GSocketEvent event)
_GSocket_GDK_Input, (gpointer)socket);
}
void _GSocket_Uninstall_Fallback(GSocket *socket, GSocketEvent event)
void _GSocket_Uninstall_Callback(GSocket *socket, GSocketEvent event)
{
int c;
gint *m_id;

View File

@ -59,7 +59,7 @@ void _GSocket_GUI_Destroy(GSocket *socket)
free(socket->m_gui_dependent);
}
void _GSocket_Install_Fallback(GSocket *socket, GSocketEvent event)
void _GSocket_Install_Callback(GSocket *socket, GSocketEvent event)
{
int *m_id;
@ -88,7 +88,7 @@ void _GSocket_Install_Fallback(GSocket *socket, GSocketEvent event)
}
}
void _GSocket_Uninstall_Fallback(GSocket *socket, GSocketEvent event)
void _GSocket_Uninstall_Callback(GSocket *socket, GSocketEvent event)
{
int c;
int *m_id;

View File

@ -16,11 +16,11 @@ void _GSocket_GUI_Destroy(GSocket *socket)
{
}
void _GSocket_Install_Fallback(GSocket *socket, GSocketEvent event)
void _GSocket_Install_Callback(GSocket *socket, GSocketEvent event)
{
}
void _GSocket_Uninstall_Fallback(GSocket *socket, GSocketEvent event)
void _GSocket_Uninstall_Callback(GSocket *socket, GSocketEvent event)
{
}

View File

@ -88,6 +88,8 @@ GSocket *GSocket_new()
socket->m_stream = TRUE;
socket->m_gui_dependent = NULL;
socket->m_blocking = FALSE;
socket->m_timeout = 10*60*1000;
// 10 minutes * 60 sec * 1000 millisec
/* We initialize the GUI specific entries here */
_GSocket_GUI_Init(socket);
@ -132,7 +134,7 @@ void GSocket_Shutdown(GSocket *socket)
/* We also disable GUI callbacks */
for (evt=0;evt<GSOCK_MAX_EVENT;evt++)
_GSocket_Uninstall_Fallback(socket, evt);
_GSocket_Uninstall_Callback(socket, evt);
}
/* Address handling */
@ -267,6 +269,9 @@ GSocketError GSocket_SetServer(GSocket *sck)
return GSOCK_IOERR;
}
GSocket_SetNonBlocking(sck, sck->m_blocking);
GSocket_SetTimeout(sck, sck->m_timeout);
return GSOCK_NOERROR;
}
@ -338,6 +343,9 @@ GSocketError GSocket_SetNonOriented(GSocket *sck)
return GSOCK_IOERR;
}
GSocket_SetBlocking(sck, sck->m_blocking);
GSocket_SetTimeout(sck, sck->m_timeout);
return GSOCK_NOERROR;
}
@ -393,6 +401,9 @@ GSocketError GSocket_Connect(GSocket *sck, GSocketStream stream)
/* It is not a server */
sck->m_server = FALSE;
GSocket_SetBlocking(sck, sck->m_blocking);
GSocket_SetTimeout(sck, sck->m_timeout);
return GSOCK_NOERROR;
}
@ -461,10 +472,10 @@ bool GSocket_DataAvailable(GSocket *socket)
/* Flags */
/*
GSocket_SetBlocking() puts the socket in non-blocking mode. This is useful
GSocket_SetNonBlocking() puts the socket in non-blocking mode. This is useful
if we don't want to wait.
*/
void GSocket_SetBlocking(GSocket *socket, bool block)
void GSocket_SetNonBlocking(GSocket *socket, bool block)
{
assert(socket != NULL);
@ -474,6 +485,24 @@ void GSocket_SetBlocking(GSocket *socket, bool block)
ioctl(socket->m_fd, FIONBIO, &block);
}
/*
* GSocket_SetTimeout()
*/
void GSocket_SetTimeout(GSocket *socket, unsigned long millisec)
{
assert(socket != NULL);
socket->m_timeout = millisec;
if (socket->m_fd != -1) {
struct timeval tval;
tval.tv_sec = millisec / 1000;
tval.tv_usec = (millisec % 1000) * 1000;
setsockopt(socket->m_fd, SOL_SOCKET, SO_SNDTIMEO, &tval, sizeof(tval));
setsockopt(socket->m_fd, SOL_SOCKET, SO_RCVTIMEO, &tval, sizeof(tval));
}
}
/*
GSocket_GetError() returns the last error occured on the socket stream.
*/
@ -498,7 +527,7 @@ GSocketError GSocket_GetError(GSocket *socket)
Server socket -> a client request a connection
LOST: the connection is lost
SetFallback accepts a combination of these flags so a same callback can
SetCallback accepts a combination of these flags so a same callback can
receive different events.
An event is generated only once and its state is reseted when the relative
@ -506,8 +535,8 @@ GSocketError GSocket_GetError(GSocket *socket)
For example: INPUT -> GSocket_Read()
CONNECTION -> GSocket_Accept()
*/
void GSocket_SetFallback(GSocket *socket, GSocketEventFlags event,
GSocketFallback fallback, char *cdata)
void GSocket_SetCallback(GSocket *socket, GSocketEventFlags event,
GSocketCallback fallback, char *cdata)
{
int count;
@ -520,17 +549,17 @@ void GSocket_SetFallback(GSocket *socket, GSocketEventFlags event,
socket->m_fbacks[count] = fallback;
socket->m_data[count] = cdata;
_GSocket_Install_Fallback(socket, count);
_GSocket_Install_Callback(socket, count);
_GSocket_Enable(socket, count);
}
}
}
/*
UnsetFallback will disables all fallbacks specified by "event".
UnsetCallback will disables all fallbacks specified by "event".
NOTE: event may be a combination of flags
*/
void GSocket_UnsetFallback(GSocket *socket, GSocketEventFlags event)
void GSocket_UnsetCallback(GSocket *socket, GSocketEventFlags event)
{
int count = 0;
@ -540,7 +569,7 @@ void GSocket_UnsetFallback(GSocket *socket, GSocketEventFlags event)
if ((event & (1 << count)) != 0) {
_GSocket_Disable(socket, count);
socket->m_fbacks[count] = NULL;
_GSocket_Uninstall_Fallback(socket, count);
_GSocket_Uninstall_Callback(socket, count);
}
}
}
@ -567,14 +596,14 @@ void _GSocket_Enable(GSocket *socket, GSocketEvent event)
{
socket->m_iocalls[event] = TRUE;
if (socket->m_fbacks[event])
_GSocket_Install_Fallback(socket, event);
_GSocket_Install_Callback(socket, event);
}
void _GSocket_Disable(GSocket *socket, GSocketEvent event)
{
socket->m_iocalls[event] = FALSE;
if (socket->m_fbacks[event])
_GSocket_Uninstall_Fallback(socket, event);
_GSocket_Uninstall_Callback(socket, event);
}
int _GSocket_Recv_Stream(GSocket *socket, char *buffer, int size)

View File

@ -17,9 +17,10 @@ struct _GSocket {
GSocketError m_error;
bool m_blocking, m_server, m_stream, m_oriented;
unsigned long m_timeout;
/* Fallbacks */
GSocketFallback m_fbacks[GSOCK_MAX_EVENT];
/* Callbacks */
GSocketCallback m_fbacks[GSOCK_MAX_EVENT];
char *m_data[GSOCK_MAX_EVENT];
/* IO calls associated */
@ -45,8 +46,8 @@ int _GSocket_Recv_Stream(GSocket *socket, char *buffer, int size);
int _GSocket_Recv_Dgram(GSocket *socket, char *buffer, int size);
int _GSocket_Send_Stream(GSocket *socket, const char *buffer, int size);
int _GSocket_Send_Dgram(GSocket *socket, const char *buffer, int size);
void _GSocket_Install_Fallback(GSocket *socket, GSocketEvent count);
void _GSocket_Uninstall_Fallback(GSocket *socket, GSocketEvent count);
void _GSocket_Install_Callback(GSocket *socket, GSocketEvent count);
void _GSocket_Uninstall_Callback(GSocket *socket, GSocketEvent count);
void _GSocket_Detected_Read(GSocket *socket);
void _GSocket_Detected_Write(GSocket *socket);
void _GSocket_GUI_Init(GSocket *socket);