TheNetNode-CB/src/l3sock.c

447 lines
17 KiB
C
Executable File

#include "tnn.h"
#ifdef TCP_STACK
TSOCKET sockets[NUM_SOCKETS];
static int SocketAlloc(void); /* Ein socket anlegen. */
static BOOLEAN SearchPort(ULONG); /* Pruefen, ob LocalPort belegt ist. */
/* Ein socket anlegen. */
int Socket(int domain, int type, int protocol)
{
register int i;
if ((i = SocketAlloc()) == EOF) /* Neuen Socket erstellen.*/
return(EOF); /* Kein Socket mehr frei. */
sockets[i].Socket = i; /* Socket setzen. */
sockets[i].Domain = domain; /* Domain setzen. */
sockets[i].Type = type; /* Protokoll-Typ setzen. */
sockets[i].State = TCP_SOCKET; /* Socket-Status setzen. */
sockets[i].tos = 0; /* Typ of Service. */
sockets[i].TState = TCP_CLOSED; /* TCP-Statusaenderungen. */
sockets[i].IpDest = 0; /* IP-Adresse vom Nachbarn. */
sockets[i].RecvNext = 0; /* Next-Frame. */
sockets[i].SendNext = 0; /* Sequence Number */
sockets[i].SendUnacked = 0; /* Sequence Number */
sockets[i].LocalPort = 0; /* Local-Port setzen. */
sockets[i].PacNum = 0; /* Frame-Zahler. */
sockets[i].MaxListen = 0; /* Groesse der Warteschlange. */
sockets[i].Listen = 0; /* Momentan in der Warteschlange. */
sockets[i].RecvEvent = FALSE; /* Select Signalisieren - Empfang. */
sockets[i].SendEvent = FALSE; /* Select Signalisieren - Senden. */
sockets[i].DestPort = 0; /* Nachbar-Port. */
sockets[i].UrgPointer = 0; /* Urgent Pointer. */
return(i); /* Neuer Socket. */
}
/* Verbindungsbau annehmen/ablehnen. */
int Accept(int s, struct Sockaddr *addr, Socklen_t *addrlen)
{
TSOCKET *sock = &sockets[s];
int NewSock;
struct Sockaddr_in sin;
if (!sock) /* Angegebener Socket wurde nicht in der Socket-Liste gefunden. */
return(EOF); /* Abbrechen. */
memset(&sin, 0, sizeof(sin)); /* Frischer Buffer holen. */
sin.sin_family = AF_INET; /* Type setzen. */
sin.sin_port = Htons((unsigned short)sock->LocalPort); /* Local-Port*/
/* setzen. */
sin.sin_addr._S_addr = sock->IpDest; /* IP-Adresse setzen. */
memcpy(addr, &sin, *addrlen);
sock->RecvEvent = FALSE; /* Select - Empfang ausschalten. */
sock->SendEvent = FALSE; /* Select - Sender ausschalten. */
if ((NewSock = Socket(sock->Domain, sock->Type, 0)) == EOF) /* Neuen Socket*/
/* anlegen. */
return(EOF); /* Neuer Socket kann nicht erstellt werden. */
sockets[NewSock].Socket = NewSock;
sockets[NewSock].State = TCP_CONNECTED; /* Socket-Status auf */
/* CONNECTED setzen. */
sockets[NewSock].TState = TCP_SYNCON;/* Verbindungsaufbau bestaetigen. */
sockets[NewSock].IpDest = sock->IpDest; /* IP-Adresse setzen. */
sockets[NewSock].RecvNext = sock->RecvNext;
sockets[NewSock].SendNext = sock->SendNext;
sockets[NewSock].SendUnacked = sock->SendUnacked;
sockets[NewSock].tos = sock->tos; /* Type of Service setzen. */
sockets[NewSock].LocalPort = sock->LocalPort; /* Local-Port setzen. */
sockets[NewSock].DestPort = sock->DestPort; /* Nachbar-Port setzen. */
sockets[NewSock].UrgPointer = sock->UrgPointer; /* Urgent Pointer setzen. */
sock->Listen--;
return(NewSock); /* Neuer Socket. */
}
/* Socket schliessen. */
void Close(int Sock)
{
register int i;
for (i = 1; i < NUM_SOCKETS; ++i) /* Durchsuche die Socket-Liste. */
{
if (sockets[i].Socket != Sock) /* Socketvergleich. */
continue; /* Zum naechsten Eintrag. */
if (sockets[i].State == TCP_CONNECTED) /* Socket mit Status CONNECTED. */
{
switch (sockets[i].TState) /* TCP-Status. */
{
case TCP_ACKWAIT : /* Status Stabil: Warte auf ACK-Bestaetigung. */
if (sockets[i].PacNum) /* Es liegen noch Frames an. */
sockets[i].TState = TCP_PSHWAITFIN; /* Neuer Status: Sende alle */
else /* offenstehende Packete. */
sockets[i].TState = TCP_ACKWAITFIN;/* Neuer Status: Warte auf ACK,*/
return; /* danach FIN senden. */
case TCP_ESTABLISHED : /* Verbindung ist stabil. */
if (sockets[i].PacNum) /* Es liegen noch Frames an. */
sockets[i].TState = TCP_PSHSENTFIN; /* Neuer Status:Naechstes */
else /* Packet senden. */
sockets[i].TState = TCP_FINSENT; /* Neuer Status: Socket sofort */
return; /* schliessen. */
default :
return;
}
}
DelSock(sockets[i].Socket); /* Socket entsorgen. */
return;
}
}
/* Socket binden. */
int Bind(int s, struct Sockaddr *name, Socklen_t namelen)
{
TSOCKET *sock = &sockets[s];
if (!sock) /* Angegebener Socket wurde nicht in der Socket-Liste gefunden. */
return(EOF); /* Abbrechen. */
if (sock->State != TCP_SOCKET) /* Socket-Status muss auf TCP_SOCKET stehen. */
return(EOF); /* Status stimmt nicht ueberein. */
if (SearchPort(((struct Sockaddr_in *)name)->sin_port)) /* Pruefe, ob der */
/* Port belegt ist. */
return(EOF); /* Abbrechen.. */
sock->LocalPort = Ntohs(((struct Sockaddr_in *)name)->sin_port);/* Port und */
sock->State = TCP_BIND; /* Socket-Status BIND setzen. */
return(FALSE);
}
/* Lausche auf Socket. */
int Listen(int s, int Number)
{
TSOCKET *sock = &sockets[s];
if (!sock) /* Angegebener Socket wurde nicht in der Socket-Liste gefunden. */
return(EOF); /* Abbrechen. */
if (sock->State != TCP_BIND) /* Kein Status BIND */
return(EOF); /* Abbrechen. */
sock->MaxListen = Number; /* Groesse der Warteschlange setzen. */
sock->State = TCP_LISTEN; /* Socket-Status auf LISTEN setzen. */
return(FALSE);
}
/* Daten Empfangen. */
int Recv(int Sock, char *Buffer, int Len, int flag)
{
TSOCKET *sock = &sockets[Sock];
#ifdef L1TCPIP
DATENRX *Drx;
#endif /* L1TCPIP */
int DataLen = 0;
int i = 0;
if (!sock) /* Angegebener Socket wurde nicht in der Socket-Liste gefunden. */
return(EOF); /* Abbrechen. */
if (sock->TState >= TCP_CLOSE) /* Socket soll geschlossen werden. */
{
sock->TState = TCP_CLOSED;
return(EOF); /* Dann machen wir das.. */
}
#ifdef L1TCPIP
if ((Drx = GetBuffer(sock)) == NULL) /* Buffer aus der EmpfangsListe holen. */
return(FALSE); /* Kein eintrag gefunden. */
DataLen = Drx->Data->mbpc - Drx->Data->mbgc; /* Gesamtlaenge ermitteln. */
while (DataLen--) /* Zeichen in Buffer schreiben. */
{
if (Len == i) /* Buffergroesse beachten. */
break; /* Wenn zu gross, abbrechen. */
Buffer[i++] = getchr(Drx->Data); /* Schreibe in Buffer. */
}
if (Drx->Data->mbpc == Drx->Data->mbgc) /* Alle zeichen verarbeitet. */
{
sock->RecvEvent = FALSE; /* Select Empfang ausschalten. */
dealmb((MBHEAD *)Drx->Data); /* Buffer entsorgen. */
dealoc((MBHEAD *)ulink((LEHEAD *)Drx)); /* TX Segment entsorgen. */
}
else
{
relink((LEHEAD *) Drx, ((LEHEAD *)rxDaten.tail)); /* Umhaengen in die RX*/
/* Buffer-Liste. */
sock->RecvEvent = TRUE; /* Select siginalisieren Empfang ein. */
}
#endif /* TCP_L1TCPIP */
return(i); /* Anzahl zeichen im Buffer. */
}
/* Daten Senden. */
int Send(int Sock, char *Buffer, int DataLen, int Flag)
{
TSOCKET *sock = &sockets[Sock];
MBHEAD *Data = NULL;
int i = 0;
if (!sock) /* Angegebener Socket wurde nicht in der Socket-Liste gefunden. */
return(EOF); /* Abbrechen. */
if (sock->TState >= TCP_CLOSE) /* Socket soll geschlossen werden. */
{
sock->TState = TCP_CLOSED;
return(EOF); /* Keine weiteren Daten senden. */
}
if (DataLen) /* Es gibt was zusenden. */
{
if ((Data = (MBHEAD *)allocb(ALLOC_TCPSTACK)) == NULL)/* Buffer besorgen. */
return(FALSE); /* Buffer ist voll. */
while (DataLen--) /* Alle zeichen in Buffer schreiben. */
{
if (i == 214) /* Maximum Segment Size erreicht. */
{
rwndmb(Data); /* Buffer zurueck spulen. */
PutTXStack(sock->Socket, /* In die Sende-Liste haengen. */
Data,
Data->mbpc - Data->mbgc,
(TACK + TPSH),
TCP_PSHSENT);
sock->SendEvent = FALSE; /* Select signalisieren Sender aus. */
sock->SendNext += i; /* Sequence Number aktualisieren. */
return(i); /* Anzahl zeichen im Buffer. */
}
putchr(Buffer[i++], Data); /* Schreibe zeichen in Buffer. */
}
rwndmb(Data); /* Buffer zurueckspulen. */
PutTXStack(sock->Socket, /* In die Sende-Liste haengen. */
Data,
Data->mbpc - Data->mbgc,
(TACK + TPSH),
TCP_PSHSENT);
sock->SendEvent = FALSE; /* Select signalisieren Sender aus. */
sock->SendNext += i; /* Sequence Number aktualisieren. */
}
return(i); /* Anzahl zeichen im Buffer. */
}
/* Den Socket auf Aktivitaet pruefen. */
int SelScan(int max_fd, Fd_set *readset, Fd_set *writeset, Fd_set *exceptset)
{
int nready = 0;
register int i;
Fd_set lreadset,
lwriteset,
lexceptset;
FD_ZERO_T(&lreadset); /* Filedescriptoren entleeren. */
FD_ZERO_T(&lwriteset);
FD_ZERO_T(&lexceptset);
for (i = 1; i < NUM_SOCKETS; ++i) /* Durchsuche die Socket-Liste. */
{
if (FD_ISSET_T(sockets[i].Socket, readset)) /* Socketvergleich - Read. */
{
if (sockets[i].RecvEvent) /* Es liegen daten in der Empfangsliste. */
{
FD_SET_T((unsigned)sockets[i].Socket, &lreadset); /* Socket setzen. */
nready++; /* Markiere, es wird was empfangen. */
}
}
if (FD_ISSET_T(sockets[i].Socket, writeset)) /* Socketvergleich - Write. */
{
if (sockets[i].SendEvent) /* Es liegen daten in der Sendeliste. */
{
FD_SET_T((unsigned)sockets[i].Socket, &lwriteset); /* Socket setzen. */
nready++; /* Markiere, es wird was gesendet. */
}
}
}
*readset = lreadset; /* Aktion weiterleiten. */
*writeset = lwriteset;
FD_ZERO_T(exceptset); /* Filedescriptoren entleeren. */
return nready;
}
/* Den Socket auf Aktivitaet pruefen. */
int Select(int max_fd,
Fd_set *readset,
Fd_set *writeset,
Fd_set *exceptset,
struct Timeval *timeout)
{
int nready;
Fd_set lreadset,
lwriteset,
lexceptset;
if (readset) /* Es soll auf Lesen geprueft werden. */
lreadset = *readset; /* Socket-liste uebergeben.*/
else
FD_ZERO_T(&lreadset); /* Filedescriptoren entleeren. */
if (writeset) /* Es soll auf Schreiben geprueft werden. */
lwriteset = *writeset; /* Socket-liste uebergeben.*/
else
FD_ZERO_T(&lwriteset); /* Filedescriptoren entleeren. */
FD_ZERO_T(&lexceptset); /* Filedescriptoren entleeren. */
nready = SelScan(max_fd, /* Den Socket auf Aktivitaet pruefen. */
&lreadset,
&lwriteset,
&lexceptset);
if (readset) /* Es soll auf lesen geprueft werden. */
*readset = lreadset; /* Neue Socket-liste uebergeben. */
if (writeset) /* Es soll auf schreiben geprueft werden. */
*writeset = lwriteset; /* Neue Socket-liste uebergeben. */
return nready;
}
/* Einen neuen Socket anlegen. */
static int SocketAlloc(void)
{
register int i;
for(i = 1; i < NUM_SOCKETS; i++) /* Durchsuche die Socketliste. */
{
if (sockets[i].State == TCP_CLOSED) /* Eintrag ist frei. */
return(i); /* Neuer Socket. */
}
return(EOF); /* Kein freier Eintrag vorhanden. */
}
/* Pruefe, ob der Socket in der Filedescriptoren-Liste steht. */
BOOLEAN GetSocket(Socklen_t Sock, Fd_set *rmask)
{
unsigned int i;
for (i = 0; i < rmask->fd_count; i++) /* Durchsuche alle FD-Eintraege. */
{ /* Neuen Eintrag ermitteln und */
if ((Socklen_t)rmask->fd_array[i] == Sock) /* vergleichen. */
return(TRUE); /* Socket gefunden. */
}
return(FALSE); /* Kein Socket gefunden. */
}
/* Pruefe, ob der Local-Port belegt ist. */
static BOOLEAN SearchPort(ULONG LocalPort)
{
register int i;
for (i = 1; i < NUM_SOCKETS; ++i) /* Durchsuche die Socketliste. */
{
if (sockets[i].LocalPort == LocalPort) /* Portvergleich. */
return(TRUE); /* Port ist schon belegt. */
}
return(FALSE); /* Kein Port gefunden. */
}
/* Den Socket aus der Socketliste suchen. */
int SearchSock(int Sock)
{
register int i;
for (i = 1; i < NUM_SOCKETS; ++i) /* Durchsuche die Socketliste. */
{
if (sockets[i].Socket == Sock) /* Socketvergleich. */
return(sockets[i].Socket); /* Socket gefunden. */
}
return(EOF); /* Kein Socket gefunden oder mittlerweile entsorgt. */
}
/* Socket als unbenutzt markieren. */
void DelSocket(int Sock)
{
register int i;
for (i = 1; i < NUM_SOCKETS; ++i) /* Durchsuche die Socketliste. */
{
if (sockets[i].Socket != Sock) /* Socketvergleich. */
continue; /* Zum naechsten socket. */
sockets[i].State = TCP_CLOSED; /* Markiere socket als unbenutzt. */
return;
}
}
/* konvertiert die Kurzganzzahl hostshort Rechner- nach Netzwerk-Byteordnung.*/
unsigned short
Htons(unsigned short n)
{
return ((n & 0xff) << 8) | ((n & 0xff00) >> 8);
}
/* konvertiert die Kurzganzzahl netshort von Netzwerk- nach Rechner-Byteordnung. */
unsigned short
Ntohs(unsigned short n)
{
return Htons(n);
}
/* konvertiert die Langganzzahl hostlong von Rechner- nach Netzwerk-Byteordnung. */
unsigned long
Htonl(unsigned long n)
{
return ((n & 0xff) << 24) |
((n & 0xff00) << 8) |
((n & 0xff0000) >> 8) |
((n & 0xff000000) >> 24);
}
/* konvertiert die Langganzzahl netlong von Netzwerk- nach Rechner-Byteordnung. */
unsigned long
Ntohl(unsigned long n)
{
return Htonl(n);
}
#endif /* TCPSTACK */
/* End of src/l3sock.c */