pull/9/head
bebopagogo 2020-05-18 10:19:28 -04:00
parent 2c34e3bf26
commit f49de2c510
7 changed files with 62 additions and 30 deletions

View File

@ -207,12 +207,22 @@ class NormSocket
NormSessionHandle GetMulticastSession() const NormSessionHandle GetMulticastSession() const
{return mcast_session;} {return mcast_session;}
NormObjectHandle GetTxStream() const
{return tx_stream;}
void InitRxStream(NormObjectHandle rxStream) void InitRxStream(NormObjectHandle rxStream)
{rx_stream = rxStream;} {rx_stream = rxStream;}
NormObjectHandle GetRxStream() const NormObjectHandle GetRxStream() const
{return rx_stream;} {return rx_stream;}
void SetFlowControl(bool state)
{
tx_flow_control = state;
if (NORM_OBJECT_INVALID != tx_stream)
NormStreamSetPushEnable(tx_stream, state ? false : true);
}
void InitTxStream(NormObjectHandle txStream, unsigned int bufferSize, UINT16 segmentSize, UINT16 blockSize) void InitTxStream(NormObjectHandle txStream, unsigned int bufferSize, UINT16 segmentSize, UINT16 blockSize)
{ {
tx_stream = txStream; tx_stream = txStream;
@ -223,6 +233,7 @@ class NormSocket
tx_stream_bytes_remain = 0; tx_stream_bytes_remain = 0;
tx_watermark_pending = false; tx_watermark_pending = false;
tx_ready = true; tx_ready = true;
NormStreamSetPushEnable(tx_stream, tx_flow_control ? false : true);
} }
bool Open(NormInstanceHandle instance = NORM_INSTANCE_INVALID); bool Open(NormInstanceHandle instance = NORM_INSTANCE_INVALID);
@ -244,13 +255,9 @@ class NormSocket
// hard, immediate closure // hard, immediate closure
void Close(); void Close();
void SetSocketInfo(NormSocketInfo* socketInfo) // for server-side, client sockets only void SetSocketInfo(NormSocketInfo* socketInfo) // for server-side, client sockets only
{socket_info = socketInfo;} {socket_info = socketInfo;}
NormSocketInfo* FindSocketInfo(NormNodeHandle client) NormSocketInfo* FindSocketInfo(NormNodeHandle client)
{return client_table.FindSocketInfo(client);} {return client_table.FindSocketInfo(client);}
void RemoveSocketInfo(NormSocketInfo& socketInfo) // for server sockets only void RemoveSocketInfo(NormSocketInfo& socketInfo) // for server sockets only
@ -350,6 +357,7 @@ class NormSocket
unsigned int tx_stream_buffer_count; unsigned int tx_stream_buffer_count;
unsigned int tx_stream_bytes_remain; unsigned int tx_stream_bytes_remain;
bool tx_watermark_pending; bool tx_watermark_pending;
bool tx_flow_control;
// Receive stream state // Receive stream state
NormObjectHandle rx_stream; NormObjectHandle rx_stream;
const void* user_data; // for use by user application const void* user_data; // for use by user application
@ -366,6 +374,7 @@ NormSocket::NormSocket(NormSessionHandle normSession)
tx_stream(NORM_OBJECT_INVALID), tx_ready(false), tx_segment_size(0), tx_stream(NORM_OBJECT_INVALID), tx_ready(false), tx_segment_size(0),
tx_stream_buffer_max(0), tx_stream_buffer_count(0), tx_stream_buffer_max(0), tx_stream_buffer_count(0),
tx_stream_bytes_remain(0), tx_watermark_pending(false), tx_stream_bytes_remain(0), tx_watermark_pending(false),
tx_flow_control(true),
rx_stream(NORM_OBJECT_INVALID), user_data(NULL) rx_stream(NORM_OBJECT_INVALID), user_data(NULL)
{ {
// For now we use the NormSession "user data" option to associate // For now we use the NormSession "user data" option to associate
@ -732,7 +741,6 @@ bool NormSocket::Connect(const char* serverAddr,
else else
{ {
// Set timeout for connect attempt (for "heavyweight" mcast connect, this would also be done) // Set timeout for connect attempt (for "heavyweight" mcast connect, this would also be done)
TRACE("NormSetUserTimer(1) session: %p\n", norm_session);
NormSetUserTimer(norm_session, NORM_DEFAULT_CONNECT_TIMEOUT); NormSetUserTimer(norm_session, NORM_DEFAULT_CONNECT_TIMEOUT);
} }
server_socket = NULL; // this is a client-side socket server_socket = NULL; // this is a client-side socket
@ -769,9 +777,14 @@ unsigned int NormSocket::Write(const char* buffer, unsigned int numBytes)
InitTxStream(tx_stream, 2*1024*1024, 1400, 16); InitTxStream(tx_stream, 2*1024*1024, 1400, 16);
} }
// This method uses NormStreamWrite(), but limits writes by explicit ACK-based flow control status if (!tx_flow_control)
if (tx_stream_buffer_count < tx_stream_buffer_max)
{ {
unsigned int bytesWritten = NormStreamWrite(tx_stream, buffer, numBytes);
return bytesWritten;
}
else if (tx_stream_buffer_count < tx_stream_buffer_max)
{
// This method uses NormStreamWrite(), but limits writes by explicit ACK-based flow control status
// 1) How many buffer bytes are available? // 1) How many buffer bytes are available?
unsigned int bytesAvailable = tx_segment_size * (tx_stream_buffer_max - tx_stream_buffer_count); unsigned int bytesAvailable = tx_segment_size * (tx_stream_buffer_max - tx_stream_buffer_count);
bytesAvailable -= tx_stream_bytes_remain; // unflushed segment portiomn bytesAvailable -= tx_stream_bytes_remain; // unflushed segment portiomn
@ -878,7 +891,6 @@ void NormSocket::Shutdown()
if ((IsServerSide() && IsMulticastClient()) || (NORM_OBJECT_INVALID == tx_stream)) if ((IsServerSide() && IsMulticastClient()) || (NORM_OBJECT_INVALID == tx_stream))
{ {
// Use a zero-timeout to immediately post NORM_SOCKET_CLOSE notification // Use a zero-timeout to immediately post NORM_SOCKET_CLOSE notification
TRACE("NormSetUserTimer(2) session: %p\n", norm_session);
NormSetUserTimer(norm_session, 0.0); NormSetUserTimer(norm_session, 0.0);
} }
else if (NORM_OBJECT_INVALID != tx_stream) else if (NORM_OBJECT_INVALID != tx_stream)
@ -892,7 +904,6 @@ void NormSocket::Shutdown()
else else
{ {
// Use a zero-timeout to immediately post NORM_SOCKET_CLOSE notification // Use a zero-timeout to immediately post NORM_SOCKET_CLOSE notification
TRACE("NormSetUserTimer(6) session: %p\n", norm_session);
NormSetUserTimer(norm_session, 0.0); NormSetUserTimer(norm_session, 0.0);
} }
} // end NormSocket::Shutdown() } // end NormSocket::Shutdown()
@ -914,7 +925,6 @@ void NormSocket::Close()
NormNodeHandle node = NormGetAckingNodeHandle(mcast_session, nodeId); NormNodeHandle node = NormGetAckingNodeHandle(mcast_session, nodeId);
assert(NORM_NODE_INVALID != node); assert(NORM_NODE_INVALID != node);
NormSocket* clientSocket = (NormSocket*)NormNodeGetUserData(node); NormSocket* clientSocket = (NormSocket*)NormNodeGetUserData(node);
TRACE("NormSetUserTimer(3) session: %p\n", clientSocket->norm_session);
NormSetUserTimer(clientSocket->norm_session, 0.0); NormSetUserTimer(clientSocket->norm_session, 0.0);
} }
// for mcast server mcast_session == norm_session so it's destroyed below // for mcast server mcast_session == norm_session so it's destroyed below
@ -1068,7 +1078,6 @@ void NormSocket::GetSocketEvent(const NormEvent& event, NormSocketEvent& socketE
// We use the session timer to dispatch a NORM_SOCKET_CLOSE per failed client // We use the session timer to dispatch a NORM_SOCKET_CLOSE per failed client
// (This will also remove the client from this server's acking list) // (This will also remove the client from this server's acking list)
clientSocket->socket_state = CLOSING; clientSocket->socket_state = CLOSING;
TRACE("NormSetUserTimer(4) session: %p\n", clientSocket->norm_session);
NormSetUserTimer(clientSocket->norm_session, 0.0); NormSetUserTimer(clientSocket->norm_session, 0.0);
} }
} }
@ -1134,7 +1143,6 @@ void NormSocket::GetSocketEvent(const NormEvent& event, NormSocketEvent& socketE
case CONNECTING: case CONNECTING:
// TBD - We should validate that it's the right remote sender // TBD - We should validate that it's the right remote sender
// (i.e., by source address and/or nodeId) // (i.e., by source address and/or nodeId)
TRACE("NormCancelUserTimer(1) norm_session: %p\n", norm_session);
NormCancelUserTimer(norm_session); NormCancelUserTimer(norm_session);
socketEvent.type = NORM_SOCKET_CONNECT; socketEvent.type = NORM_SOCKET_CONNECT;
NormSetSynStatus(norm_session, false); NormSetSynStatus(norm_session, false);
@ -1628,6 +1636,19 @@ NormSessionHandle NormGetSocketSession(NormSocketHandle normSocket)
return s->GetSession(); return s->GetSession();
} // end NormGetSocketSession() } // end NormGetSocketSession()
NormObjectHandle NormGetSocketTxStream(NormSocketHandle normSocket)
{
NormSocket* s = (NormSocket*)normSocket;
return s->GetTxStream();
} // end NormGetSocketTxStream()
NormObjectHandle NormGetSocketRxStream(NormSocketHandle normSocket)
{
NormSocket* s = (NormSocket*)normSocket;
return s->GetRxStream();
} // end NormGetSocketRxStream()
NormSessionHandle NormGetSocketMulticastSession(NormSocketHandle normSocket) NormSessionHandle NormGetSocketMulticastSession(NormSocketHandle normSocket)
{ {
NormSocket* s = (NormSocket*)normSocket; NormSocket* s = (NormSocket*)normSocket;
@ -1639,4 +1660,10 @@ void NormSetSocketTrace(NormSocketHandle normSocket, bool enable)
{ {
NormSocket* s = (NormSocket*)normSocket; NormSocket* s = (NormSocket*)normSocket;
s->SetTrace(enable); s->SetTrace(enable);
} } // end NormSetSocketTrace()
void NormSetSocketFlowControl(NormSocketHandle normSocket, bool enable)
{
NormSocket* s = (NormSocket*)normSocket;
s->SetFlowControl(enable);
} // end NormSetSocketFlowControl()

View File

@ -101,7 +101,10 @@ NormInstanceHandle NormGetSocketInstance(NormSocketHandle normSocket);
NormSessionHandle NormGetSocketSession(NormSocketHandle normSocket); NormSessionHandle NormGetSocketSession(NormSocketHandle normSocket);
NormSessionHandle NormGetSocketMulticastSession(NormSocketHandle normSocket); NormSessionHandle NormGetSocketMulticastSession(NormSocketHandle normSocket);
void NormGetPeerName(NormSocketHandle normSocket, char* addr, unsigned int* addrLen, UINT16* port); void NormGetPeerName(NormSocketHandle normSocket, char* addr, unsigned int* addrLen, UINT16* port);
NormObjectHandle NormGetSocketTxStream(NormSocketHandle normSocket);
NormObjectHandle NormGetSocketRxStream(NormSocketHandle normSocket);
void NormSetSocketFlowControl(NormSocketHandle normSocket, bool enable);
void NormSetSocketTrace(NormSocketHandle normSocket, bool enable); void NormSetSocketTrace(NormSocketHandle normSocket, bool enable);
typedef enum NormSocketEventType typedef enum NormSocketEventType

View File

@ -52,7 +52,10 @@ class NormObject
// This must be reset after each update // This must be reset after each update
void SetNotifyOnUpdate(bool state) void SetNotifyOnUpdate(bool state)
{notify_on_update = state;} {
TRACE("enter SetNotifyOnUpdate(%d) ...\n", state);
notify_on_update = state;
}
// Object information // Object information
NormObject::Type GetType() const {return type;} NormObject::Type GetType() const {return type;}

@ -1 +1 @@
Subproject commit 7cf50bddf3939e5bd78f7264e1baa8b8643d4cd7 Subproject commit 0e6731b7d61ea78f8ca9bfeb32e73c19bbeb40dd

View File

@ -220,11 +220,8 @@ void NormInstance::Notify(NormController::Event event,
{ {
case SEND_OK: case SEND_OK:
// Purge any pending NORM_SEND_ERROR notifications for session // Purge any pending NORM_SEND_ERROR notifications for session
TRACE("purging SEND_ERROR ...\n");
PurgeNotifications(session, NORM_SEND_ERROR); PurgeNotifications(session, NORM_SEND_ERROR);
return; return;
case SEND_ERROR:
TRACE("got SEND_ERROR\n");
default: default:
break; break;
} }
@ -557,7 +554,6 @@ bool NormInstance::GetNextEvent(NormEvent* theEvent)
case NORM_SEND_ERROR: case NORM_SEND_ERROR:
{ {
NormSession* session = (NormSession*)next->event.session; NormSession* session = (NormSession*)next->event.session;
TRACE("calling ClearSendError() ....\n");
session->ClearSendError(); session->ClearSendError();
break; break;
} }
@ -1878,8 +1874,9 @@ NormObjectHandle NormStreamOpen(NormSessionHandle sessionHandle,
NormSession* session = (NormSession*)sessionHandle; NormSession* session = (NormSession*)sessionHandle;
if (session) if (session)
{ {
NormStreamObject* streamObj = session->QueueTxStream(bufferSize, true, infoPtr, infoLen);
NormObject* obj = NormObject* obj =
static_cast<NormObject*>(session->QueueTxStream(bufferSize, true, infoPtr, infoLen)); static_cast<NormObject*>(streamObj);
if (obj) objectHandle = (NormObjectHandle)obj; if (obj) objectHandle = (NormObjectHandle)obj;
} }
instance->dispatcher.ResumeThread(); instance->dispatcher.ResumeThread();

View File

@ -3521,14 +3521,20 @@ bool NormStreamObject::Read(char* buffer, unsigned int* buflen, bool seekMsgStar
bytesWanted = *buflen; bytesWanted = *buflen;
} }
bool result = ReadPrivate(buffer, buflen, seekMsgStart); bool result = ReadPrivate(buffer, buflen, seekMsgStart);
if (!read_ready) notify_on_update = true; if (!read_ready)
{
notify_on_update = true;
}
if (!seekMsgStart && result && (0 != *buflen) && (*buflen < bytesWanted)) if (!seekMsgStart && result && (0 != *buflen) && (*buflen < bytesWanted))
{ {
char dummyBuffer[8]; char dummyBuffer[8];
unsigned int dummyCount = 8; unsigned int dummyCount = 8;
stream_broken = ReadPrivate(dummyBuffer, &dummyCount, false) ? false : true; stream_broken = ReadPrivate(dummyBuffer, &dummyCount, false) ? false : true;
ASSERT(0 == dummyCount); ASSERT(0 == dummyCount);
if (!read_ready) notify_on_update = true; if (!read_ready)
{
notify_on_update = true;
}
} }
return result; return result;
} // end NormStreamObject::Read() } // end NormStreamObject::Read()
@ -3553,7 +3559,7 @@ bool NormStreamObject::ReadPrivate(char* buffer, unsigned int* buflen, bool seek
NormBlock* block = stream_buffer.Find(read_index.block); NormBlock* block = stream_buffer.Find(read_index.block);
if (NULL == block) if (NULL == block)
{ {
//DMSG(0, "NormStreamObject::ReadPrivate() stream buffer empty (1) (sbEmpty:%d)\n", stream_buffer.IsEmpty()); PLOG(PL_DETAIL, "NormStreamObject::ReadPrivate() stream buffer empty (1) (sbEmpty:%d)\n", stream_buffer.IsEmpty());
read_ready = false; read_ready = false;
*buflen = bytesRead; *buflen = bytesRead;
if (bytesRead > 0) if (bytesRead > 0)
@ -3614,8 +3620,8 @@ bool NormStreamObject::ReadPrivate(char* buffer, unsigned int* buflen, bool seek
if (NULL == segment) if (NULL == segment)
{ {
//DMSG(0, "NormStreamObject::ReadPrivate(%lu:%hu) stream buffer empty (read_offset>%lu) (2)\n", PLOG(PL_DETAIL, "NormStreamObject::ReadPrivate(%lu:%hu) stream buffer empty (read_offset>%lu) (2)\n",
// (unsigned long)read_index.block.GetValue(), read_index.segment, (unsigned long)read_offset); (unsigned long)read_index.block.GetValue(), read_index.segment, (unsigned long)read_offset);
read_ready = false; read_ready = false;
*buflen = bytesRead; *buflen = bytesRead;
if (bytesRead > 0) if (bytesRead > 0)

View File

@ -254,8 +254,6 @@ bool NormSession::Open()
if (!tx_socket->SetFragmentation(fragmentation)) if (!tx_socket->SetFragmentation(fragmentation))
PLOG(PL_WARN, "NormSession::Open() warning: tx_socket.SetFragmentation() error\n"); PLOG(PL_WARN, "NormSession::Open() warning: tx_socket.SetFragmentation() error\n");
TRACE("NormSession::Open() address %s\n", address.GetHostString());
if (address.IsMulticast()) if (address.IsMulticast())
{ {
if (!tx_socket->SetTTL(ttl)) if (!tx_socket->SetTTL(ttl))
@ -2240,7 +2238,6 @@ void NormSession::TxSocketRecvHandler(ProtoSocket& theSocket,
} }
else else
{ {
TRACE("NormSession::TxSocketRecvHandler() RecvFrom error\n");
// Probably an ICMP "port unreachable" error // Probably an ICMP "port unreachable" error
// Note we purposefull do _not_ set the "posted_send_error" // Note we purposefull do _not_ set the "posted_send_error"
// status here because we do not want this notification // status here because we do not want this notification
@ -2362,14 +2359,13 @@ void NormSession::RxSocketRecvHandler(ProtoSocket& theSocket,
} }
else else
{ {
TRACE("NormSession::RxSocketRecvHandler() RecvFrom error address:%s (unicast:%d)\n", Address().GetHostString(), Address().IsUnicast()); //TRACE("NormSession::RxSocketRecvHandler() RecvFrom error address:%s (unicast:%d)\n", Address().GetHostString(), Address().IsUnicast());
// Probably an ICMP "port unreachable" error // Probably an ICMP "port unreachable" error
// Note we purposefull do _not_ set the "posted_send_error" // Note we purposefull do _not_ set the "posted_send_error"
// status here because we do not want this notification // status here because we do not want this notification
// cleared due to SEND_OK status since it's receiver driven // cleared due to SEND_OK status since it's receiver driven
if (Address().IsUnicast()) if (Address().IsUnicast())
{ {
TRACE("posting send error ...\n");
Notify(NormController::SEND_ERROR, NULL, NULL); Notify(NormController::SEND_ERROR, NULL, NULL);
} }
break; break;