Files
SyncHome/trunk/Arduino/libraries/ENC28J60/utility/socket.c
2023-03-17 11:59:21 +00:00

422 lines
13 KiB
C

#include "socket.h"
#include "net.h"
#include "enc28j60.h"
#include "ip_arp_udp_tcp.h"
#define BUFFER_SIZE 550
#define MAX_ITERATIONS 1000
#define NO_STATE 0
#define GOT_MAC 1
#define ARP_REQUEST_SENT 2
#define TCP_SYN_SENT 3
uint8_t myMacAddress[6], myIpAddress[4], myGatewayIpAddress[4],
mySubnetAddress[4];
static uint8_t buffer[BUFFER_SIZE + 1];
uint16_t packetLength, sendPacketLength = 0;
#ifdef ETHERSHIELD_DEBUG
uint8_t SOCKET_DEBUG[80];
uint8_t *socketDebug() {
return SOCKET_DEBUG;
}
void socketClearDebug() {
//free(SOCKET_DEBUG);
//SOCKET_DEBUG = (uint8_t *) malloc(sizeof(uint8_t));
SOCKET_DEBUG[0] = 255;
}
void ethershieldDebug(uint8_t debugCode) {
uint8_t i;
for (i = 0; SOCKET_DEBUG[i] != 255; i++) {}
SOCKET_DEBUG[i++] = debugCode;
SOCKET_DEBUG[i] = 255;
/*
int i, j, w;
for (i = 0; SOCKET_DEBUG[i] != '\0'; i++) {}
for (j = 0; toAdd[j] != '\0'; j++) {}
SOCKET_DEBUG = (char *) realloc(SOCKET_DEBUG, i + j + 2);
if (i > 0) {
SOCKET_DEBUG[i++] = '\n';
}
for (w = 0; w < j; w++, i++) {
SOCKET_DEBUG[i] = toAdd[w];
}
SOCKET_DEBUG[i] = '\0';
*/
}
char *debugCode2String(uint8_t debugCode) {
if (debugCode == DEBUG_RECEIVED_ARP_REPLY) {
return "RECEIVED_ARP_REPLY";
}
else if (debugCode == DEBUG_ANSWERING_RECEIVED_ARP_REQUEST) {
return "ANSWERING_RECEIVED_ARP_REQUEST";
}
else if (debugCode == DEBUG_IGNORING_PACKET_NOT_FOR_ME) {
return "IGNORING_PACKET_NOT_FOR_ME";
}
else if (debugCode == DEBUG_REPLYING_ECHO_REQUEST) {
return "REPLYING_ECHO_REQUEST";
}
else if (debugCode == DEBUG_IGNORED_PACKET) {
return "IGNORED_PACKET";
}
else if (debugCode == DEBUG_RECEIVED_TCP_SYNACK_SENDING_ACK) {
return "RECEIVED_TCP_SYNACK_SENDING_ACK";
}
else if (debugCode == DEBUG_RECEIVED_TCP_SYN_SENDING_SYNACK) {
return "RECEIVED_TCP_SYN_SENDING_SYNACK";
}
else if (debugCode == DEBUG_RECEIVED_ACKFIN_CLOSING_SOCKET) {
return "RECEIVED_ACKFIN_CLOSING_SOCKET";
}
else if (debugCode == DEBUG_RECEIVED_ACK_PACKET_HAVE_NO_DATA) {
return "DONT_KNOW_WHAT_TO_DO";
}
else if (debugCode == DEBUG_DONT_KNOW_WHAT_TO_DO) {
return "DONT_KNOW_WHAT_TO_DO";
}
else if (debugCode == DEBUG_SENT_ARP_REQUEST) {
return "SENT_ARP_REQUEST";
}
else if (debugCode == DEBUG_MAC_RECEIVED_SENDING_TCP_SYN) {
return "MAC_RECEIVED_SENDING_TCP_SYN";
}
else if (debugCode == DEBUG_TCP_SYN_SENT) {
return "TCP_SYN_SENT";
}
else if (debugCode == DEBUG_INIT) {
return "INIT";
}
}
#endif
typedef struct socketData {
uint8_t protocol;
uint16_t sourcePort;
uint8_t flag;
uint8_t state;
uint8_t *buffer;
uint16_t bytesToRead;
uint16_t firstByte;
uint8_t clientState;
uint8_t destinationMac[6];
} SocketData;
SocketData _SOCKETS[MAX_SOCK_NUM];
#ifdef ETHERSHIELD_DEBUG
void turnLEDsOn() {
enc28j60PhyWrite(PHLCON, 0x880); //turn on
}
void turnLEDsOff() {
enc28j60PhyWrite(PHLCON, 0x990); //turn off
}
#endif
uint8_t socket(SOCKET s, uint8_t protocol, uint16_t sourcePort, uint8_t flag) {
_SOCKETS[s].protocol = protocol;
_SOCKETS[s].sourcePort = sourcePort;
_SOCKETS[s].flag = flag;
_SOCKETS[s].state = SOCK_INIT;
_SOCKETS[s].bytesToRead = 0;
_SOCKETS[s].firstByte = 0;
_SOCKETS[s].clientState = NO_STATE;
}
void flushSockets() {
uint16_t data;
packetLength = enc28j60PacketReceive(BUFFER_SIZE, buffer);
if (!packetLength) {
//DEBUG: no data available for reading!
return;
}
else if (eth_type_is_arp_and_my_ip(buffer, packetLength)) {
if (arp_packet_is_myreply_arp(buffer)) {
uint8_t i;
#ifdef ETHERSHIELD_DEBUG
ethershieldDebug(DEBUG_RECEIVED_ARP_REPLY);
#endif
for (i = 0; i < 6; i++) {
_SOCKETS[0].destinationMac[i] = buffer[ETH_SRC_MAC + i];
}
_SOCKETS[0].clientState = GOT_MAC;
//TODO: write code to get socket id instead of 0
}
else {
#ifdef ETHERSHIELD_DEBUG
ethershieldDebug(DEBUG_ANSWERING_RECEIVED_ARP_REQUEST);
#endif
make_arp_answer_from_request(buffer);
}
}
else if (!eth_type_is_ip_and_my_ip(buffer, packetLength)) {
#ifdef ETHERSHIELD_DEBUG
ethershieldDebug(DEBUG_IGNORING_PACKET_NOT_FOR_ME);
#endif
return;
}
else if (buffer[IP_PROTO_P] == IP_PROTO_ICMP_V &&
buffer[ICMP_TYPE_P] == ICMP_TYPE_ECHOREQUEST_V) {
#ifdef ETHERSHIELD_DEBUG
//char myStr[80];
//sprintf(myStr, "Replying ECHO REQUEST from %d.%d.%d.%d",
// buffer[IP_SRC_IP_P], buffer[IP_SRC_IP_P + 1],
// buffer[IP_SRC_IP_P + 2], buffer[IP_SRC_IP_P + 3]);
ethershieldDebug(DEBUG_REPLYING_ECHO_REQUEST);
#endif
make_echo_reply_from_request(buffer, packetLength);
}
else if (buffer[IP_PROTO_P] == IP_PROTO_TCP_V) {
//DEBUG: it's TCP and for me! Do I want it?
uint16_t destinationPort = (buffer[TCP_DST_PORT_H_P] << 8) | buffer[TCP_DST_PORT_L_P];
uint8_t i, socketSelected = 255;
for (i = 0; i < MAX_SOCK_NUM; i++) {
if (_SOCKETS[i].sourcePort == destinationPort &&
_SOCKETS[i].state == SOCK_LISTEN) {
socketSelected = i;
break;
}
}
if (socketSelected == 255) {
#ifdef ETHERSHIELD_DEBUG
//char myStr[80];
//sprintf(myStr, "Packet from: %d.%d.%d.%d:%d ignored.",
// buffer[IP_SRC_IP_P], buffer[IP_SRC_IP_P + 1],
// buffer[IP_SRC_IP_P + 2], buffer[IP_SRC_IP_P + 3],
// destinationPort);
ethershieldDebug(DEBUG_IGNORED_PACKET);
#endif
//return; //TODO: return!
socketSelected = 0; //TODO: remove this hack
}
//TODO: change next 'if' to 'else if'
//DEBUG: ok, the TCP packet is for me and I want it.
if (buffer[TCP_FLAGS_P] == (TCP_FLAG_SYN_V | TCP_FLAG_ACK_V)) {
#ifdef ETHERSHIELD_DEBUG
ethershieldDebug(DEBUG_RECEIVED_TCP_SYNACK_SENDING_ACK);
#endif
//TODO: verify if I'm waiting for this SYN+ACK
make_tcp_ack_from_any(buffer); //TODO: send ACK using tcp_client_send_packet
_SOCKETS[socketSelected].clientState = SOCK_ESTABLISHED;
//TODO: write code to get socket id instead of 0
return;
}
else if (buffer[TCP_FLAGS_P] & TCP_FLAGS_SYN_V) {
#ifdef ETHERSHIELD_DEBUG
ethershieldDebug(DEBUG_RECEIVED_TCP_SYN_SENDING_SYNACK);
#endif
_SOCKETS[socketSelected].state = SOCK_ESTABLISHED;
make_tcp_synack_from_syn(buffer);
}
else if (buffer[TCP_FLAGS_P] & TCP_FLAGS_ACK_V) {
init_len_info(buffer);
data = get_tcp_data_pointer();
if (!data) {
if (buffer[TCP_FLAGS_P] & TCP_FLAGS_FIN_V) {
#ifdef ETHERSHIELD_DEBUG
ethershieldDebug(DEBUG_RECEIVED_ACKFIN_CLOSING_SOCKET);
#endif
make_tcp_ack_from_any(buffer);
_SOCKETS[socketSelected].state = SOCK_CLOSED;
}
return;
}
else {
#ifdef ETHERSHIELD_DEBUG
ethershieldDebug(DEBUG_RECEIVED_ACK_PACKET_HAVE_NO_DATA);
#endif
int i, dataSize = packetLength - (&buffer[data] - buffer);
_SOCKETS[socketSelected].state = SOCK_ESTABLISHED;
_SOCKETS[socketSelected].buffer = malloc((BUFFER_SIZE) * sizeof(uint8_t)); //TODO: and about the TCP/IP/Ethernet overhead?
for (i = 0; i < dataSize; i++) {
_SOCKETS[socketSelected].buffer[i] = buffer[data + i];
}
_SOCKETS[socketSelected].bytesToRead = i;
//make_tcp_ack_from_any(buffer);
return;
}
}
else {
#ifdef ETHERSHIELD_DEBUG
ethershieldDebug(DEBUG_DONT_KNOW_WHAT_TO_DO);
#endif
}
}
}
uint8_t listen(SOCKET s) {
_SOCKETS[s].state = SOCK_LISTEN;
return 1;
}
uint8_t connect(SOCKET s, uint8_t *destinationIp, uint16_t destinationPort) {
uint16_t packetChecksum, i, sourcePort;
char buffer[59];
#ifdef ETHERSHIELD_DEBUG
char myStr[80];
#endif
//TODO: create an ARP table?
make_arp_request(buffer, destinationIp);
_SOCKETS[s].clientState = ARP_REQUEST_SENT;
#ifdef ETHERSHIELD_DEBUG
ethershieldDebug(DEBUG_SENT_ARP_REQUEST);
#endif
for (i = 0; _SOCKETS[s].clientState != GOT_MAC && i < MAX_ITERATIONS; i++) {
flushSockets(); //it'll fill destinationMac on socket struct
}
if (_SOCKETS[s].clientState != GOT_MAC) {
return 0;
}
#ifdef ETHERSHIELD_DEBUG
ethershieldDebug(DEBUG_MAC_RECEIVED_SENDING_TCP_SYN);
#endif
sourcePort = 42845; //TODO: change this
tcp_client_send_packet(buffer, destinationPort, sourcePort, TCP_FLAG_SYN_V,
1, 1, 0, 0, _SOCKETS[s].destinationMac,
destinationIp);
_SOCKETS[s].clientState = TCP_SYN_SENT;
#ifdef ETHERSHIELD_DEBUG
ethershieldDebug(DEBUG_TCP_SYN_SENT);
#endif
for (i = 0; _SOCKETS[s].clientState != SOCK_ESTABLISHED && i < MAX_ITERATIONS; i++) {
flushSockets();
}
#ifdef ETHERSHIELD_DEBUG
//sprintf(myStr, "Socket state = %d (SOCK_ESTABLISHED = %d)",
// _SOCKETS[s].clientState, SOCK_ESTABLISHED);
//ethershieldDebug(myStr);
#endif
return _SOCKETS[s].clientState == SOCK_ESTABLISHED;
//TODO: Maybe use a timeout instead of MAX_ITERATIONS to receive SYN+ACK
}
uint16_t send(SOCKET s, const uint8_t *bufferToSend, uint16_t length) {
sendPacketLength = fill_tcp_data2(buffer, sendPacketLength, bufferToSend, length);
} //TODO: do it per socket
uint16_t recv(SOCKET s, uint8_t *buffer, uint16_t length) {
int i, j;
if (!_SOCKETS[s].bytesToRead) {
return;
}
else if (length == 1) {
buffer[0] = _SOCKETS[s].buffer[_SOCKETS[s].firstByte];
_SOCKETS[s].firstByte++;
if (_SOCKETS[s].firstByte == _SOCKETS[s].bytesToRead) {
_SOCKETS[s].bytesToRead = 0;
_SOCKETS[s].firstByte = 0;
free(_SOCKETS[s].buffer);
}
}
/*
for (i = _SOCKETS[s].firstByte, j = 0; i < _SOCKETS[s].bytesToRead && i < length; i++, j++) {
buffer[j] = _SOCKETS[s].buffer[i];
}
if (i + 1 == _SOCKETS[s].bytesToRead) {
free(_SOCKETS[s].buffer);
_SOCKETS[s].firstByte = 0;
_SOCKETS[s].bytesToRead = 0;
}
else {
_SOCKETS[s].bytesToRead -= i;
_SOCKETS[s].firstByte = i;
}
*/
}
uint8_t disconnect(SOCKET s) {
if (sendPacketLength) {
make_tcp_ack_from_any(buffer);
make_tcp_ack_with_data(buffer, sendPacketLength);
sendPacketLength = 0;
}
//TODO: send FYN packet
//TODO: wait to receive ACK?
_SOCKETS[s].state = SOCK_CLOSED; //TODO: remove this hack
}
uint8_t close(SOCKET s) {
//do not call the function that does verifications
_SOCKETS[s].state = SOCK_CLOSED;
}
uint8_t getSn_SR(SOCKET s) {
//get socket status
//TODO: change on standard Ethernet library to do not use this
flushSockets();
return _SOCKETS[s].state;
}
uint16_t getSn_RX_RSR(SOCKET s) {
//return the size of the receive buffer for that socket
//TODO: change on standard Ethernet library to do not use this
flushSockets();
return _SOCKETS[s].bytesToRead;
}
void iinchip_init() {
//TODO: change on standard Ethernet library to do not use this
//do nothing
#ifdef ETHERSHIELD_DEBUG
socketClearDebug();
#endif
}
void sysinit(uint8_t txSize, uint8_t rxSize) {
//TODO: change on standard Ethernet library to do not use this
uint8_t i;
for (i = 0; i < MAX_SOCK_NUM; i++) {
_SOCKETS[i].state = SOCK_CLOSED;
}
#ifdef ETHERSHIELD_DEBUG
ethershieldDebug(DEBUG_INIT);
#endif
}
void setSHAR(uint8_t *macAddress) {
//TODO: change on standard Ethernet library to do not use this
uint8_t i;
for (i = 0; i < 6; i++) {
myMacAddress[i] = macAddress[i];
}
enc28j60Init(myMacAddress);
enc28j60clkout(2);
enc28j60PhyWrite(PHLCON, 0x476); //LEDA = link status, LEDB = RX/TX
}
void setSIPR(uint8_t *ipAddress) {
//TODO: change on standard Ethernet library to do not use this
uint8_t i;
for (i = 0; i < 4; i++) {
myIpAddress[i] = ipAddress[i];
}
}
void setGAR(uint8_t *gatewayIpAddress) {
//TODO: change on standard Ethernet library to do not use this
uint8_t i;
for (i = 0; i < 4; i++) {
myGatewayIpAddress[i] = gatewayIpAddress[i];
}
}
void setSUBR(uint8_t *subnetAddress) {
//TODO: change on standard Ethernet library to do not use this
uint8_t i;
for (i = 0; i < 4; i++) {
mySubnetAddress[i] = subnetAddress[i];
}
init_ip_arp_udp_tcp(myMacAddress, myIpAddress, 1); //TODO: change this port
}