/*
sendbuffer sends "length" bytes from "buffer" through the socket "sock".
*/
size_t sendbuffer(struct socket *sock, const char *buffer, size_t length)
{
struct msghdr msg;
mm_segment_t oldfs; // mm_segment_t is just a long
struct iovec iov; // structure containing a base addr. and length
int len2;
//printk("entering sendbuffer\n");
msg.msg_name = 0;
msg.msg_namelen = 0;
msg.msg_iov = &iov;
msg.msg_iovlen = 1; //point to be noted
msg.msg_control = null;
msg.msg_controllen = 0;
msg.msg_flags = msg_nosignal; //0/*msg_dontwait*/;
iov.iov_base = (char*) buffer; // as we know that iovec is
iov.iov_len = (__kernel_size_t) length; // nothing but a base addr and length
// #define get_fs() (current_thread_info()->addr_limit)
// similar for set_fs;
/*
therefore this line sets the "fs" to kernel_ds and saves its old value
*/
oldfs = get_fs();
set_fs(kernel_ds);
/* actual sending of the message */
len2 = sock_sendmsg(sock, &msg, (size_t)(length));
/* retrieve the old value of fs (whatever it is) */
set_fs(oldfs);
return len2;
}
/*
recieves data from the socket "sock" and puts it in the 'buffer'.
returns the length of data recieved
the calling function must do a:
buffer = (char*) get_free_page(gfp_kernel);
or a kmalloc to allocate kernel's memory
(or it can use the kernel's stack space [very small] )
*/
size_t recvbuffer(struct socket *sock, const char *buffer, size_t length)
{
struct msghdr msg;
struct iovec iov;
int len;
mm_segment_t oldfs;
/* set the msghdr structure*/
msg.msg_name = 0;
msg.msg_namelen = 0;
msg.msg_iov = &iov;
msg.msg_iovlen = 1;
msg.msg_control = null;
msg.msg_controllen = 0;
msg.msg_flags = 0;
/* set the iovec structure*/
iov.iov_base = (void *) &buffer[0];
iov.iov_len = (size_t)length;
/* recieve the message */
oldfs = get_fs();
set_fs(kernel_ds);
len = sock_recvmsg(sock,&msg,length,0/*msg_dontwait*/); // let it wait if there is no message
set_fs(oldfs);
// if ((len!=-eagain)&&(len!=0))
// printk("recvbuffer recieved %i bytes \n",len);
return len;
}
/*
sets up a server-side socket
1. create a new socket
2. bind the address to the socket
3. start listening on the socket
*/
struct socket* set_up_server_socket(int port_no)
{
struct socket *sock;
struct sockaddr_in sin;
int error;
/* first create a socket */
error = sock_create(pf_inet,sock_stream,ipproto_tcp,&sock) ;
if (error<0)
printk("error during creation of socket; terminating\n");
/* now bind the socket */
sin.sin_family = af_inet;
sin.sin_addr.s_addr = inaddr_any;
sin.sin_port = htons(port_no);
error = sock->ops->bind(sock,(struct sockaddr*)&sin,sizeof(sin));
if (error<0)
{
printk("error binding socket \n");
return 0;
}
/* now, start listening on the socket */
error=sock->ops->listen(sock,32);
if (error!=0)
printk("error listening on socket \n");
/* now start accepting */
// accepting is performed by the function server_accept_connection
return sock;
}
/*
accepts a new connection (server calls this function)
1. create a new socket
2. call socket->ops->accept
3. return the newly created socket
*/
struct socket* server_accept_connection(struct socket *sock)
{
struct socket * newsock;
int error;
/* before accept: clone the socket */
error = sock_create(pf_inet,sock_stream,ipproto_tcp,&newsock);
if (error<0)
printk("error during creation of the other socket; terminating\n");
newsock->type = sock->type;
newsock->ops=sock->ops;
/* do the actual accept */
error = newsock->ops->accept(sock,newsock,0);
if (error<0)
{
/* must add release the socket code here */
printk("error accepting socket\n") ;
return 0;
}
return newsock;
}
struct socket * set_up_client_socket(unsigned int ip_addr, int port_no)
{
struct socket *clientsock;
struct sockaddr_in sin;
int error, i;
/* first create a socket */
error = sock_create(pf_inet,sock_stream,ipproto_tcp,&clien tsock);
if (error<0)
{
printk("error during creation of socket; terminating\n");
return 0;
}
/* now bind and connect the socket */
sin.sin_family = af_inet;
sin.sin_addr.s_addr = htonl(ip_addr);
sin.sin_port = htons(port_no);
for(i=0; i<10; i)
{
error = clientsock->ops->connect(clientsock,(struct sockaddr*)&sin,sizeof(sin),0);
if (error<0)
{
printk("error connecting client socket to server: %i, retrying .. %d \n",error, i);
if(i == 10-1)
{
printk("giving up!\n");
return 0;
}
}
else
break; //connected
}
return clientsock;
}
|