/*
*********************************************************************************************************
* uC/OS-II
* The Real-Time Kernel
*
* (c) Copyright 2011
* All Rights Reserved
*
* File : socket.c
* By : Weekope Chou
*********************************************************************************************************
*/
#include "socket.h"
#include "ucos_ii.h"
INT32S sockFD = -1;
Socket clientSockets[10];
INT32S clientIndex = -1;
/*
Socket_Create() Socket_Bind() Socket_Listen()三个函数必须同时依次使用,客户端建立套接字时需要绑定操作
*/
/*
*********************************************************************************************************
* Create Socket
*
* Description: This function create Socket with specified domain、type and protocol.
*
* Arguments : domain is a flag for a group of IP
*
* type defines the type of data
*
* protocol defines the protocol to be used
*
* Returns : sockFD Socket descriper
*********************************************************************************************************
*/
INT32U Socket_Create(INT16U domain, INT32U type, INT32U protocol){
//Initiate Socket array only when there is no Socket created
if(sockFD == -1){
INT32U arrayIndex = 0;
//Create arraySocket with all elements initiated
ip_addr iniSrcAddr;
ip_addr iniDesAddr;
Mbuf * iniSendBuff;
Mbuf * iniRcvBuff;
TCP_tcb * iniTcb;
//Initiate Socket
Socket iniSocket;
iniSocket.domain = 0;
iniSocket.sockFD = -1;
iniSocket.type = 0;
iniSocket.protocol = 0;
iniSocket.srcPort = 0;
iniSocket.desPort = 0;
iniSocket.srcAddr = iniSrcAddr;
iniSocket.desAddr = iniDesAddr;
iniSocket.sendbuf = iniSendBuff;
iniSocket.rcvbuf = iniRcvBuff;
//iniSocket.sin_zero;
iniSocket.s_tcb = iniTcb;
for(arrayIndex; arrayIndex < 10; arrayIndex++){
arraySocket[arrayIndex] = iniSocket;
}
}
//Create Socket
sockFD++;
arraySocket[sockFD].domain = domain;
arraySocket[sockFD].type = type;
arraySocket[sockFD].protocol = protocol;
//Return sockFD as descriper
return sockFD;
}
/*
*********************************************************************************************************
* Bind Socket
*
* Description: This function binds local Socket with sockFD.
*
* Arguments : sockFD local Socket descriper
*
* p_thisAddr local Socket
*
* addrLen size of Socket
*
* Returns : ==1 successful
*
* ==0 failed
*********************************************************************************************************
*/
INT8U Socket_Bind(INT32U sockFD, Socket * p_thisAddr, INT32U addrLen){
//Bind sockFD with Socket
arraySocket[sockFD].sockFD = sockFD;
//Binding successful
return SUCCESSFUL;
}
/*
*********************************************************************************************************
* Setup Listen Socket
*
* Description: This function setups Listen Socket and wait for connection request.
*
* Arguments : sockFD local Socket descriper
*
* backLog request array lenth
*
* Returns : ==1 successful
*
* ==0 failed
*********************************************************************************************************
*/
INT8U Socket_Listen(INT32U serverFD, INT32U backLog){ //Listen sockFD不可变
//在主模块中需要创建常量保存服务器sockFD,并赋值Listen
Socket * clientSocket; //serverFD = Socket_Create()
Mbuf * p_mbuf;
clientSocket = &clientSockets[clientIndex];
p_mbuf->m_socket = clientSocket;
//Create connection
if(syn){
syn = 0;
//Get SYN diagram and send back ACK+SYN diagram
clientSocket->s_tcb->tt_controlbit = ACK | SYN;
TCP_Output(p_mbuf);
while(1){
//Wait for ACK diagram
OSTimeDlyHMSM(0,0,1,0);
//TCP connection has been done
if(ack){
ack = 0;
//Compare requesting Socket with listening Socket
if(arraySocket[sockFD].srcAddr.s_addr == clientSocket->srcAddr.s_addr && arraySocket[sockFD].srcPort == clientSocket->srcPort){
listenConfirm = 1;
return SUCCESSFUL;
}
}
}
}
//Close connection
if(fin){
fin = 0;
//Get FIN diagram and send back ACK diagram and FIN diagram
clientSocket->s_tcb->tt_controlbit = ACK;
TCP_Output(p_mbuf);
clientSocket->s_tcb->tt_controlbit = FIN;
TCP_Output(p_mbuf);
while(1){
//Wait for ACK diagram
OSTimeDlyHMSM(0,0,1,0);
if(ack){
ack = 0;
return SUCCESSFUL;
}
}
}
return FAILED;
}
/*
*********************************************************************************************************
* Send Connection Request
*
* Description: This function sends connection request.
*
* Arguments : sockFD local Socket descriper
*
* p_serverAddr server Socket
*
* addrLen size of Socket
*
* Returns : ==1 successful
*
* ==0 failed
*********************************************************************************************************
*/
INT8U Socket_Connect(INT32U sockFD, Socket * p_serverSocket, INT32U addrLen){
Mbuf * p_mbuf;
//Put client Socket into clientSockets[]
clientIndex++;
clientSockets[clientIndex] = arraySocket[sockFD];
//Send SYN diagram
p_mbuf->m_socket = p_serverSocket;
p_serverSocket->s_tcb->tt_controlbit = SYN;
TCP_Output(p_mbuf);
while(1){
//Wait for ACK+SYN diagram
OSTimeDlyHMSM(0,0,1,0);
//Wait until get ACK+SYN diagram
if(ackAndsyn){
ackAndsyn = 0;
//Get ACK+SYN diagram and send back ACK diagram
p_serverSocket->s_tcb->tt_controlbit = ACK;
TCP_Output(p_mbuf);
return SUCCESSFUL;
}
}
}
/*
*********************************************************************************************************
* Accept Connection Request
*
* Description: This function accept connection request and save client's Socket.
*
* Arguments : sockFD local Socket descriper
*
* p_serverAddr server Socket
*
* addrLen size of Socket
*
* Returns : ==1 successful
*
* ==0 failed
*********************************************************************************************************
*/
INT8U Socket_Accept(INT32U sockFD, Socket * newSocket, INT32U * addrLen){
if(1){ //我不知道什么条件失败,呵呵
//Get client Socket
newSocket = &clientSockets[clientIndex];
return SUCCESSFUL;
}
else return FAILED;
}
/*
**************************************************************
*
* 考虑缓冲区长度和发送接受数据大小之间的关系
*
**************************************************************
*/
/*
*********************************************************************************************************
* Send TCP Data
*
* Description: This function sends TCP data.
*
* Arguments : sockFD local Socket descriper
*
* p_sendSocket Socket contains data to be transmitted
*
* len size of data
*
* flags Socket flag
*
* Returns : ==1 successful
*
* ==0 failed
*********************************************************************************************************
*/
INT8U Socket_Send(INT32U sockFD, Socket * p_sendSocket, INT32U len, INT8U flags){
//See if p_sendBuff.sendBuff.socket points to p_sendBuff, that is whether Socket and Mbuf connected to each other
if(sockFD == p_sendSocket->sendbuf->m_socket->sockFD){
//Get data from p_sendSocket and transmit pointer of data to TCP
TCP_Output(p_sendSocket->sendbuf);
return SUCCESSFUL;
}
else return FAILED;
}
/*
*********************************************************************************************************
* Recieve TCP Data
*
* Description: This function recieves TCP data.
*
* Arguments : sockFD local Socket descriper
*
* buff point to data to be recieved
*
* len size of buffer
*
* flags Socket flag
*
* Returns : ==1 successful
*
* ==0 failed
*********************************************************************************************************
*/
INT8U Socket_Recv(INT32U sockFD, void * buff, INT32U len, INT8U flags){
if(1){ //我不知道什么条件失败,呵呵
//Get data and put into buff
arraySocket[sockFD].rcvbuf = arraySocket[sockFD].rcvbuf->m_hdr.mh_nextpkt;
Mbuf_GetData(&arraySocket[sockFD].rcvbuf,buff,SIZE_OF_DHCPMES);
return SUCCESSFUL;
}
else return FAILED;
}
/*
*********************************************************************************************************
* Send UDP Data
*
* Description: This function sends UDP data.
*
* Arguments : sockFD local Socket descriper
*
* p_sendSocket Socket of sender
*
* len size of data
*
* flags Socket flag
*
* p_to Socket of reciever
*
* toLen size of Socket
*
* Returns : ==1 successful
*
* ==0 failed
*********************************************************************************************************
*/
INT8U Socket_SendTo(INT32U sockFD, Socket * p_sendSocket, INT32U len, INT8U flags, Socket * p_to, INT32U toLen){
//See if p_sendBuff.sendBuff.socket points to p_sendBuff, that is whether Socket and Mbuf connected to each other
if(p_to->sockFD == p_to->sendbuf->m_socket->sockFD){
//Get source/destination ip/port and data,invoke UDP interface to transmit data
UDP_Output(&arraySocket[sockFD], p_sendSocket->sendbuf, p_to->sendbuf, 0);
return SUCCESSFUL;
}
else return FAILED;
}
/*
*********************************************************************************************************
* Recieve UDP Data
*
* Description: This function recieves UDP data.
*
* Arguments : sockFD local Socket descriper
*
* buff point to data to be recieved
*
* len size of data
*
* flags Socket flag
*
* p_to Socket of reciever
*
* toLen size of Socket
*
* Returns : ==1 successful
*
* ==0 failed
*********************************************************************************************************
*/
INT8U Socket_RecvFrom(INT32U sockFD, void * buff, INT32U len, INT8U flags, Socket * p_from, INT32U fromLen){
if(1){ //我不知道什么条件失败,呵呵
//Get data and put into buff
arraySocket[sockFD].rcvbuf = arraySocket[sockFD].rcvbuf->m_hdr.mh_nextpkt;
Mbuf_GetData(&arraySocket[sockFD].rcvbuf,buff,SIZE_OF_DHCPMES);
return SUCCESSFUL;
}
else return FAILED;
}
/*
*********************************************************************************************************
* Close Socket
*
* Description: This function closes Socket. If type is SOCKET_STREAM, Socket will be closed and
*
* TCP connection will be shutdowned. If type is SOCKET_STREAM, only Socket will be closed.
*
* Arguments : sockFD local Socket descriper
*
* Returns : ==1 successful
*
* ==0 failed
*********************************************************************************************************
*/
INT8U Socket_Close(INT32U sockFD){ //此程序中需要由客户端发起关闭请求
ip_addr iniSrcAddr;
ip_addr iniDesAddr;
Mbuf * iniSendBuff;
Mbuf * iniRecvBuff;
TCP_tcb * iniTcb;
Socket desSocket;
INT32U numSocket = 0;
//Release both server and client Socket
for(numSocket; numSocket < 2; numSocket++){
arraySocket[sockFD].domain = 0;
arraySocket[sockFD].sockFD = -1;
arraySocket[sockFD].type = 0;
arraySocket[sockFD].protocol = 0;
arraySocket[sockFD].srcPort = 0;
arraySocket[sockFD].desPort = 0;
arraySocket[sockFD].srcAddr = iniSrcAddr;
arraySocket[sockFD].desAddr = iniDesAddr;
arraySocket[sockFD].sendbuf = iniSendBuff;
arraySocket[sockFD].rcvbuf = iniRecvBuff;
arraySocket[sockFD].sin_zero;
arraySocket[sockFD].s_tcb = iniTcb;
sockFD--;
}
//SOCKET_STREAM should shutdown TCP connection
if(arraySocket[sockFD].type == SOCKET_STREAM){
//Find server Socket
if(arraySocket[sockFD + 1].sockFD == -1){
desSocket = arraySocket[sockFD - 1];
}
else desSocket = arraySocket[sockFD + 1];
//Send FIN diagram
desSocket.s_tcb->tt_controlbit = FIN;
TCP_Output(desSocket.sendbuf);
while(1){
//Wait for ACK diagram and FIN diagram
OSTimeDlyHMSM(0,0,1,0);
//Wait until get FIN diagram
if(ack && fin){
ack = 0;
fin = 0;
//Send ACK diagram
desSocket.s_tcb->tt_controlbit = ACK;
TCP_Output(desSocket.sendbuf);
//Clear current client Sockets from clientSockets[]
clientIndex--;
return SUCCESSFUL;
}
}
}
//Clear current client Sockets from clientSockets[]
clientIndex--;
return SUCCESSFUL;
}