LINUX msgget and ftok - linux

Hello I'm trying IPC practice. But I have problem... Here is the code
Send_process.c (path : /home/John/h1/send_process.c)
struct mymsgbuf {
long mtype;
char mtext[80];
};
int main(void) {
key_t key;
int msgid;
struct mymsgbuf mesg;
char inputmsg[80];
if(msgid = msgget((key_t)123, IPC_CREAT | 0666) == -1) {
perror("Failed to create new MessageQueue");
exit(1);
}
printf("%d\n", msgid);
mesg.mtype = 1;
while(1) {
printf("Enter Sending Message. (Input exit, programm terminate) : ");
scanf("%s", inputmsg);
strcpy(mesg.mtext, inputmsg);
if(msgsnd(msgid, (void *)&mesg, sizeof(mesg.mtext), IPC_NOWAIT) == -1) {
perror("msgsnd");
exit(1);
}
if(strcmp(inputmsg, "exit") == 0) {
printf("Sending Process Terminated\n");
break;
}
}
return 0;
}
Receive_process.c (path : /home/John/h1/send_process.c)
struct mymsgbuf {
long mtype;
char mtext[80];
};
int main(void) {
struct mymsgbuf inmsg;
key_t key;
int msgid;
key = ftok("/home/John/h1/receive_process.c", 123);
if((msgid = msgget(key,0666)) < 0 ) { //here is error
perror("msgget");
exit(1);
}
printf("%d\n", msgid);
while(1) {
if(msgrcv(msgid, &inmsg, sizeof(inmsg.mtext), 0,0) == -1) {
perror("Message Receive");
exit(1);
}
printf("Received Message. Message is [%s]\n", inmsg.mtext);
if(strcmp(inmsg.mtext, "exit") == 0 ) {
printf("Receive_process end\n");
exit(0);
}
}
return 0;
}
Send_process is works very well, but Receive_process not works well. What is the problem?

Related

Linux kernel networking

I have aquestion about linux kernel networking.
Assume that I need to send data from kernel to client in user space. In user space I open socket in non blocking mode via issuing connect() function. Then in kernel mode I send data to connected client. Only once. The dmesg command shows me this. But in user mode it starts receiving the data eternally! Once packet received the next packet is the same one! The packet is split into 2 parts. First part is responsible for full message size. What am I doing wrong?
Here is code snippets for driver code:
Data types:
`
struct orlan_tcp_conn_handler_data
{
struct socket *socket;
};
struct orlan_tcp_service
{
volatile int running;
volatile int running_thread;
struct socket *listen_socket;
struct task_struct *thread;
struct orlan_tcp_conn_handler_data *conn_list;
};
`
Initialization:
static int tcp_server_accept(void *data)
{
struct orlan_tcp_service *orlan_data = (struct orlan_tcp_service*)data;
int err = 0;
struct socket *socket;
struct socket *accept_socket = NULL;
struct inet_connection_sock *isock;
struct orlan_tcp_conn_handler_data *conn_handler;
int error_rep_count = 0;
DECLARE_WAITQUEUE(accept_wait, current);
#ifdef MODULE_USE_TRACE
printk(KERN_INFO MODULE_NAME ": start of Accept Thread\n");
#endif
socket = orlan_data->listen_socket;
while (1)
{
accept_socket = sock_alloc();
if (!accept_socket)
{
printk(KERN_ERR MODULE_NAME ": error allocating accept socket!\n");
if (++error_rep_count == 5)
{
orlan_data->running_thread = 1;
return -(ENOMEM);
}
continue;
}
accept_socket->type = socket->type;
accept_socket->ops = socket->ops;
isock = inet_csk(socket->sk);
#ifdef MODULE_USE_TRACE
printk(KERN_INFO MODULE_NAME ": Accept Thread: before wait queue\n");
#endif
add_wait_queue(&socket->sk->sk_wq->wait, &accept_wait);
while (reqsk_queue_empty(&isock->icsk_accept_queue))
{
__set_current_state(TASK_INTERRUPTIBLE);
schedule_timeout(HZ);
if (kthread_should_stop() || signal_pending(current))
{
__set_current_state(TASK_RUNNING);
remove_wait_queue(&socket->sk->sk_wq->wait, &accept_wait);
sock_release(accept_socket);
orlan_data->running = 1;
orlan_data->running_thread = 1;
return 0;
}
}
__set_current_state(TASK_RUNNING);
remove_wait_queue(&socket->sk->sk_wq->wait, &accept_wait);
#ifdef MODULE_USE_TRACE
printk(KERN_INFO MODULE_NAME ": Accept Thread before accept\n");
#endif
orlan_data->running = 1;
orlan_data->running_thread = 1;
err = socket->ops->accept(socket, accept_socket, /*O_NONBLOCK*/0, true);
if (err < 0)
{
printk(KERN_ERR MODULE_NAME ": error accepting socket connection!\n");
sock_release(accept_socket);
if (++error_rep_count == 5)
return err;
continue;
}
#ifdef MODULE_USE_TRACE
printk(KERN_INFO MODULE_NAME ": Accept Thread: after accept\n");
#endif
if (orlan_data->conn_list)
{
sock_release(accept_socket);
error_rep_count = 0;
if (kthread_should_stop() || signal_pending(current))
break;
continue;
}
conn_handler = kmalloc(sizeof(struct orlan_tcp_conn_handler_data), GFP_KERNEL);
if (!conn_handler)
{
printk(KERN_ERR MODULE_NAME ": error allocating %u bytes!\n", (unsigned int)sizeof(struct orlan_tcp_conn_handler_data));
sock_release(accept_socket);
if (++error_rep_count == 5)
return -(ENOMEM);
continue;
}
//memset(conn_handler, 0, sizeof(struct orlan_tcp_conn_handler_data));
conn_handler->socket = accept_socket;
orlan_data->conn_list = conn_handler;
#ifdef MODULE_USE_TRACE
printk(KERN_INFO MODULE_NAME ": socket connected\n");
#endif
error_rep_count = 0;
if (kthread_should_stop() || signal_pending(current))
break;
}
#ifdef MODULE_USE_TRACE
printk(KERN_INFO MODULE_NAME ": end of Accept Thread\n");
#endif
return 0;
}
static int ktcp_start_listen(void *data)
{
struct orlan_tcp_service *orlan_data = (struct orlan_tcp_service*)data;
int err;
struct socket *conn_socket;
struct sockaddr_in server;
struct orlan_tcp_conn_handler_data *list;
#ifdef MODULE_USE_TRACE
printk(KERN_INFO MODULE_NAME ": start of Main Thread\n");
#endif
allow_signal(SIGKILL | SIGTERM);
err = sock_create(PF_INET, SOCK_STREAM, IPPROTO_TCP, &orlan_data->listen_socket);
if (err < 0)
{
orlan_data->listen_socket = NULL;
printk(KERN_ERR MODULE_NAME ": error creating main socket!\n");
orlan_data->running_thread = 1;
return err;
}
conn_socket = orlan_data->listen_socket;
orlan_data->listen_socket->sk->sk_reuse = 1;
server.sin_addr.s_addr = INADDR_ANY;
server.sin_family = AF_INET;
server.sin_port = htons(TCP_PORT);
err = conn_socket->ops->bind(conn_socket, (struct sockaddr*)&server, sizeof(server));
if (err < 0)
{
sock_release(orlan_data->listen_socket);
orlan_data->listen_socket = NULL;
printk(KERN_ERR MODULE_NAME ": error binding main socket!\n");
orlan_data->running_thread = 1;
return err;
}
err = conn_socket->ops->listen(conn_socket, /*sock_net(conn_socket->sk)->core.sysctl_somaxconn*/2);
if (err < 0)
{
sock_release(orlan_data->listen_socket);
orlan_data->listen_socket = NULL;
printk(KERN_ERR MODULE_NAME ": error listening on main socket!\n");
orlan_data->running_thread = 1;
return err;
}
tcp_server_accept(orlan_data);
list = orlan_data->conn_list;
while (list)
{
struct orlan_tcp_conn_handler_data *p = list;
if (p->socket)
sock_release(p->socket);
list = NULL;
kfree(p);
}
orlan_data->conn_list = NULL;
#ifdef MODULE_USE_TRACE
printk(KERN_INFO MODULE_NAME ": end of Main Thread\n");
#endif
sock_release(orlan_data->listen_socket);
orlan_data->listen_socket = NULL;
orlan_data->running = 0;
orlan_data->running_thread = 0;
return 0;
}
int ktcp_start(void)
{
memset(&orlan_tcp_service, 0, sizeof(orlan_tcp_service));
orlan_tcp_service.thread = kthread_run((void*)ktcp_start_listen, &orlan_tcp_service, MODULE_NAME);
if (orlan_tcp_service.thread)
{
//printk(KERN_INFO MODULE_NAME ": before waiting for listening socket creation\n");
//while (!orlan_tcp_service.running_thread);
//printk(KERN_INFO MODULE_NAME ": after waiting for listening socket creation (running = %d)\n", orlan_tcp_service.running);
//return orlan_tcp_service.running == 1 ? 0 : 1;
return 0;
}
return 1;
}
`
Send message function:
`
static int tcp_send_msg(struct socket *socket, unsigned char *buffer, unsigned long length)
{
struct msghdr msg;
struct kvec vec;
int len;
unsigned long size;
msg.msg_name = 0;
msg.msg_namelen = 0;
msg.msg_control = NULL;
msg.msg_controllen = 0;
msg.msg_flags = 0;//MSG_DONTWAIT;
vec.iov_len = length;
vec.iov_base = buffer;
size = length;
while (length)
{
printk(KERN_INFO MODULE_NAME ": before writing to socket\n");
len = kernel_sendmsg(socket, &msg, &vec, length, length);
printk(KERN_INFO MODULE_NAME ": after writing to socket\n");
if (len == -EAGAIN || len == -ERESTARTSYS)
continue;
if (len < 0)
return len;
if (len)
{
length -= (unsigned long)len;
vec.iov_len -= len;
vec.iov_base = (char*)vec.iov_base + len;
}
}
return (int)size;
}
`
Please help me,
Dmitriy
I tried to debug the problem. But nothing helped.

How do i print the char value from file c program?

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define BUFFER_SIZE 128
const char *FILE_GAME_DATA_PATH = "./game.txt";
struct game_tag
{
char gname[20];
struct game_tag *next;
} * head;
//struct game_tag g;
typedef struct game_tag GAME;
//file functions
void read_file();
//util functions.
int menu();
void print_game(GAME *game);
void release(GAME *data);
//core
void display_game();
void quite();
//link
int count_elements(GAME *elements);
int count();
int main(void)
{
int selected;
read_file();
while (1)
{
selected = menu();
switch (selected)
{
case 1:
display_game();
break;
default:
printf("cannot find your option!");
break;
}
}
}
void display_game()
{
read_file();
GAME *game = head;
if(game == NULL)
{
printf("\nNo Game!\n");
return;
}
print_game(game);
}
void print_game(GAME *game)
{
int records_count = 0;
printf("\n========== GAME ==========\n");
while(game != NULL)
{
printf("\n");
printf("Game Name: %s\n ", game->gname);
game = game->next;
records_count++;
}
printf("\nRecords: %d has been loaded successfully!\n", records_count);
release(game);
}
int menu()
{
printf("\n(1) Display Game details\n");
int choosen;
printf("\nEnter your option: ");
scanf("%d", &choosen);
return choosen;
}
void add_game(char game_name[20])
{
GAME *temp, *iterator;
temp = (struct game_tag *)malloc(sizeof(struct game_tag));
GAME info;
memcpy(info.gname, game_name, 20);
//temp = head;
iterator = head;
if (head == NULL)
{
head = temp;
head->next = NULL;
}
else
{
while (iterator->next != NULL)
{
iterator = iterator->next;
}
temp->next = NULL;
iterator->next = temp;
}
}
void read_file()
{
if(head != NULL)
{
GAME *temp;
while(head != NULL)
{
temp = head;
head = head->next;
free(temp);
}
}
FILE *file;
file = fopen(FILE_GAME_DATA_PATH, "r");
if(file == NULL)
{
printf("Cannot read file: %s", FILE_GAME_DATA_PATH);
exit(EXIT_FAILURE);
}
char game_name[20];
int i;
while(!feof(file))
{
char no[BUFFER_SIZE];
fgets(game_name, sizeof(game_name), file);
i=0;
while(game_name[i] != '\0')
{
i++;
}
game_name[i] = '\0';
add_game(game_name);
}
fclose(file);
}
void quite()
{
printf("\nGoodbye!");
exit(EXIT_SUCCESS);
}
void release(GAME *data)
{
if (data == NULL)
{
return;
}
// free the nodes
// because it can be use in memory
// we need to clear it first
// before we re-initailize the new data
GAME *temp;
while (data != NULL)
{
temp = data;
data = data->next;
free(temp);
}
}
(1) At this point, I have created the main function
(2) I'm trying to print the value from txt file which is char value that less than 20byte
(3) My error is it read the file properly, but it returns the garbage value
!Error I'm concern that my read_file function doesn't read txt proper or there an error in my condition statement

Socket Programming Error in Connect

I am trying to do Socket programming. I've google and looked at problems like mine. However, I can't see to figure out my error.
Whenever I run my code, I get an error in connect() in main in client.c. The error is invalid argument.
Server.c
/* chatroom server */
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
#include <unistd.h>
#include <netdb.h>
#include <pthread.h>
#include <signal.h>
#define MAX_ROOMS 36
#define MAX_NAME_SIZE 56
#define PORT_NUM 12333
#define MSG_SIZE 8
#define MAX_LOAD 246
#define MAX_CRC 64 //max clients
#define MAX_BUF 256
#define SERVER_IP 32
#define DEBUG 0
struct msg {
int type; //create, join, delete
int length; // length or port num
};
struct chat_room {
int socket_d; //socket descriptor
int port;
pthread_t id; //id of chatroom
char name[MAX_NAME_SIZE];
int clients[MAX_ROOMS]; // used to hold the client's master sockets
};
struct chat_room* findRoom(char* name, struct chat_room* chat){
int iterator;
for(iterator = 0; iterator < MAX_ROOMS; iterator++){
if(strcmp(name, chat[iterator].name) && (chat[iterator].port != 0)) {
return &chat[iterator];
}
}
//if room does not exist
return NULL;
}
struct chat_room* joinServer(int chat_socket, char* name, struct chat_room* chat){
struct chat_room* local_chat = findRoom(name, chat);
int i;
if(local_chat != NULL){ //if the chat exists
for(i= 0; i< MAX_CRC; i++){
if(local_chat->clients[i] == 0)
{
local_chat->clients[i] = chat_socket;
}
return local_chat;
}
}
//if server if full or else error
return NULL;
}
int createResponse(int chat_socket, int new_port_num, int type){
struct msg temp;
char temp_buff[MAX_LOAD];
memset(temp_buff, 0, MAX_LOAD);
temp.type = type;
temp.length = new_port_num;
memcpy(temp_buff, &temp, sizeof(temp));
write(chat_socket, temp_buff, MSG_SIZE);
return 0;
}
int joinResponse(int chat_socket, int new_port_num){
struct msg temp;
char temp_buff[MAX_LOAD];
memset(temp_buff, 0, MAX_LOAD);
temp.type = 11;
temp.length = new_port_num;
memcpy(temp_buff, &temp, sizeof(temp));
write(chat_socket, temp_buff, MSG_SIZE);
return 0;
}
int deleteResponse(int chat_socket, struct chat_room* chat){
struct msg temp;
char temp_buff[MAX_LOAD];
int i;
memset(temp_buff, 0, MAX_LOAD);
temp.type = 12;
memcpy(temp_buff, &temp, sizeof(temp));
for(i=0; i<MAX_CRC; i++){
if((chat->clients[i] != chat_socket) && (chat->clients[i] != 0))
write(chat->clients[i],temp_buff, MSG_SIZE);
}
return 0;
}
struct chat_room* addRoom(int chat_socket, char* name, struct chat_room* chat){
int socket_d;
int i;
struct sockaddr_in sock;
static int port = PORT_NUM;
memset(&sock, 0, sizeof(sock));
int temp = -1;
for(i = 0; i<MAX_ROOMS; i++){
if((strcmp(chat[i].name, name) == 0) && (chat[i].port != 0)){
createResponse(chat_socket, chat[i].port, 15);
return NULL;
}
else if((chat[i].port == 0) && (temp== -1)){
temp = i;
}
}
if(temp == -1){
return NULL;
}
socket_d = socket(AF_INET, SOCK_STREAM, 0);
if(socket_d == -1 && DEBUG){
perror("Error creating chatroom socket");
return NULL;
}
sock.sin_family = AF_INET;
port++;
sock.sin_port = htons(port);
if(bind(socket_d, (struct sockaddr*)&sock, sizeof(struct sockaddr_in)) == -1){
perror("error in binding ");
return NULL;
}
chat[temp].socket_d = socket_d;
chat[temp].port = port;
strcpy(chat[temp].name, name);
return &chat[temp];
}
void* chat_room_main(void* chat_room_cluster){
char buf[MAX_LOAD];
int socket_d, chat_socket;
int temp; //temp_fd
int read_val;
int num_clients = 0;
int i;
int clients[MAX_CRC];
fd_set allfd, modfd;
struct chat_room chat_room_para;
memcpy(&chat_room_para, (struct chat_room*)chat_room_cluster, sizeof(struct chat_room));
free(chat_room_cluster);
memset(clients, 0, sizeof(int)*MAX_CRC);
socket_d = chat_room_para.socket_d;
listen(socket_d, 1);
FD_ZERO(&allfd);
FD_SET(socket_d, &allfd);
printf("New Chatroom Started\n");
while(1){
modfd = allfd;
select(FD_SETSIZE, &modfd, NULL, NULL, NULL);
for(temp = 0; temp < FD_SETSIZE; temp++){
if(FD_ISSET(temp, &modfd)){
memset(buf, 0, sizeof(buf));
if(temp == socket_d) {
chat_socket = accept(socket_d, NULL, NULL);
FD_SET(chat_socket, &allfd);
// find an empty spot to add the chat room
for(i = 0; i<MAX_CRC; i++) {
if(clients[i] == 0){
clients[i] = chat_socket;
break;
}
}
sprintf(buf, "Number of people in chatroom: %d", num_clients);
write(chat_socket, buf, strlen(buf));
num_clients++;
}
else{
if(read_val = read(temp, buf, MAX_LOAD) > 0){
for(i = 0; i< MAX_CRC; i++){
if((clients[i] != temp) && (clients[i] != 0)){
write(clients[i], buf, read_val);
}
}
}
else if(read_val <= 0) {
FD_CLR(temp, &allfd);
for(i = 0; i<MAX_CRC; i++){
if(clients[i] == temp)
clients[i] = 0;
}
num_clients--;
close(chat_socket);
}
}
}
}
}
}
int main(int argc, char* argv[]){
int server_socket, chat_socket; //file descriptors for server and chat
int temp; //tempfd
int i, j;
char server_ip[SERVER_IP];
char buf[MAX_BUF];
char msg_buf[MSG_SIZE];
fd_set allfd, modfd;
struct sockaddr_in sock;
struct hostent* host_name;
struct chat_room chatrooms[MAX_ROOMS];
memset(chatrooms, '\0', sizeof(struct chat_room)* MAX_ROOMS);
memset(&sock, '\0', sizeof(sock));
server_socket = socket(AF_INET, SOCK_STREAM, 0);
if(server_socket == -1){
perror("Error creating socket");
return -1;
}
sock.sin_family = AF_INET;
sock.sin_port = htons(PORT_NUM);
sock.sin_addr.s_addr = INADDR_ANY;
if((bind(server_socket, (struct sockaddr*)&sock, sizeof(struct sockaddr_in))) == -1){
perror("Error in bind()");
return -1;
}
listen(server_socket, 1);
FD_ZERO(&allfd);
FD_SET(server_socket, &allfd);
FD_SET(0, &allfd);
printf("\n*******Chatroom Server*******");
while(1){
modfd = allfd;
select(FD_SETSIZE, &modfd, NULL, NULL, NULL);
for(temp = 0; temp < FD_SETSIZE; temp++) {
if(FD_ISSET(temp, &modfd)) {
switch(temp){
case 0:
break;
default:
if(temp == server_socket){
chat_socket = accept(server_socket, NULL, NULL);
}
else{
char msg_buf[MSG_SIZE];
char buf[MAX_LOAD];
char name[MAX_LOAD];
struct msg temp_message;
struct chat_room* local_chat = NULL;
void* (*init_chatroom)() = &chat_room_main;
void* thread_args;
pthread_attr_t attr;
pthread_t tid;
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
memset(buf, 0, sizeof(buf));
memset(msg_buf, 0, sizeof(msg_buf));
msg_buf[19]= 0;
int read_val = read(temp, msg_buf, MSG_SIZE);
if(read_val > 0){
memcpy(&temp_message, msg_buf, sizeof(temp_message));
read(temp, buf, temp_message.length - sizeof(temp_message));
memcpy(name, buf, temp_message.length - sizeof(temp_message));
if(temp_message.type == 0) {//if create
local_chat = addRoom(temp, name, chatrooms);
if(local_chat != NULL){
thread_args = (void*)malloc(sizeof(struct chat_room));
memcpy((struct chat_room*) thread_args, local_chat, sizeof(struct chat_room));
pthread_create(&tid, &attr, init_chatroom, thread_args);
local_chat->id = tid;
createResponse(temp, local_chat->port, 10);
}
}
else if(temp_message.type == 1){ //join
local_chat = joinServer(temp, name, chatrooms);
if(local_chat != NULL){
joinResponse(temp, local_chat->port);
}
}
else if(temp_message.type == 2){ //delete
local_chat = findRoom(name, chatrooms);
printf("Deleting Room\n");
if(local_chat != NULL) {
local_chat->port = 0;
close(local_chat->socket_d);
deleteResponse(temp, local_chat);
for(j = 0; j<MAX_CRC; j++){
if(local_chat->clients[j]!=0) {
FD_CLR(local_chat->clients[j], &modfd);
local_chat->clients[j] = 0;
}
}
pthread_cancel(local_chat->id);
}
}
}
else if(read_val <= 0){
FD_CLR(temp, &allfd);
close(temp);
}
}
}
}
}
}
return 0;
}
Client.c
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
#include <unistd.h>
#include <netdb.h>
#include <pthread.h>
#define PORT_NUM 12333
#define MSG_SIZE 8
#define MAX_LOAD 246
#define MAX_BUF 256
#define SERVER_IP 32
struct msg {
int type;
int length;
};
struct thread_para {
int port;
struct hostent* host_name;
};
int sendCmd(int chat_socket, char* buf, int type){ //function for sending the command
struct msg temp;
char temp_buf[MAX_LOAD];
char name[MAX_LOAD];
int iterator;
if(type == 0){
iterator = 6;
}
else if(type == 1){
iterator = 4;
}
else if(type == 2){
iterator = 6;
}
for(; iterator < strlen(buf); iterator++){
if(buf[iterator] == ' ') {
continue;
}
else{
break;
}
}
strcpy(name, buf+iterator);
memset(temp_buf, 0, MAX_LOAD);
temp.type = type;
temp.length = sizeof(temp)+strlen(name)+1; //for \0
memcpy(temp_buf, &temp, sizeof(temp));
memcpy(temp_buf+sizeof(temp), name, strlen(name)+1);
write(chat_socket, temp_buf, temp.length);
return 0;
}
void* connectChat(int port_num, struct hostent* host_name, int master){
char buf[MAX_BUF];
char temp_buf[MAX_BUF];
int chat_socket;
int i;
int input;
int temp; //temp fd
fd_set allfd, modfd;
struct sockaddr_in sock;
printf("Successfully Joined Room\n");
memset(buf, 0, sizeof(buf));
memset(&sock, 0, sizeof(sock));
sock.sin_family = AF_INET;
sock.sin_port = htons(port_num);
memcpy((char*)&sock.sin_addr.s_addr, host_name->h_addr, host_name->h_length);
chat_socket = socket(AF_INET, SOCK_STREAM, 0);
if(chat_socket == -1){
perror("Error in creation");
return NULL;
}
if(connect(chat_socket, (struct sockaddr*)&sock, sizeof(struct sockaddr)) < 0 ){
perror("Error in connection");
return NULL;
}
FD_ZERO(&allfd);
FD_SET(chat_socket, &allfd);
FD_SET(0, &allfd);
FD_SET(master, &allfd);
while(1) {
modfd = allfd;
select(FD_SETSIZE, &modfd, NULL, NULL, NULL);
for(temp = 0; temp< FD_SETSIZE; temp++){
memset(buf, 0, sizeof(buf));
memset(temp, 0, sizeof(buf));
if(temp == 0) { //reading from standard in
input = read(0, buf, MAX_BUF);
buf[input-1] = '\0'; //add termination to end
write(chat_socket, buf, strlen(buf));
}
else if(temp == chat_socket){
input = read(0, buf, MAX_BUF);
buf[input] = '\0';
memcpy(temp, buf, input);
//display message
printf("%s \n", temp_buf);
}
else if(temp == master){
struct msg temp_message;
input = read(temp, buf, MSG_SIZE);
memcpy(&temp_message, buf, MSG_SIZE);
if(temp_message.type == 12){
printf("Chatroom has been deleted, Shutting down chatroom\n");
return NULL;
}
}
}
}
return 0;
}
int main(int argc, char* argv[]){
char buf[MAX_BUF];
int chat_socket;
int i;
int input;
int temp; //temp fd
int accept_input = 1; // take input for stdin to create a chat thread
fd_set allfd, modfd;
char server_ip[SERVER_IP];
struct hostent* host_name;
struct sockaddr_in sock;
struct msg temp_message;
pthread_attr_t tattr;
pthread_t tid;
if(argc < 2) {
printf("Please try ./crc <server IP> \n");
return -1;
}
pthread_attr_init(&tattr);
pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_DETACHED);
memset(&sock, '\0', sizeof(sock));
sock.sin_family = AF_INET;
sock.sin_port = htons(PORT_NUM);
strcpy(server_ip ,argv[1]);
if((host_name = (struct hostent*)gethostbyname(server_ip)) == NULL){
perror("failed to get host name");
return -1;
}
memcpy((char*)&sock.sin_addr.s_addr, host_name->h_addr, host_name->h_length);
chat_socket = socket(AF_INET, SOCK_STREAM, 0);
if(chat_socket == -1){
perror("Error creating socket");
return -1;
}
if((connect(chat_socket, (struct sockaddr*)&sock, sizeof(sock))) < 0) {
perror("Error connecting");
return -1;
}
FD_ZERO(&allfd); /* first, clear the allfd set */
FD_SET(chat_socket, &allfd); /* adding client to the set */
FD_SET(0, &allfd);
printf("*****Welcome to the Chatroom*****\n");
while(1){
modfd = allfd;
select(FD_SETSIZE, &modfd, NULL, NULL, NULL);
for(temp = 0; temp < FD_SETSIZE; temp++){
if(FD_ISSET(temp, &modfd)){
if(temp == 0){
input = read(0, buf, MAX_BUF);
buf[input-1] = '\0'; //remove \n inserts termination
if((strncasecmp(buf, "create ", 7) == 0)) {
sendCmd(chat_socket, buf, 0);
}
else if((strncasecmp(buf, "join ", 5) == 0)) {
sendCmd(chat_socket, buf, 1);
}
else if((strncasecmp(buf, "delete ", 7)==0)){
sendCmd(chat_socket, buf, 2);
}
else
{
printf("Enter a valid command: create <Room_name>, join <Room_name>, delete <Room_name>\n");
}
}
else if(temp == chat_socket){
input = read(temp, buf, MSG_SIZE);
memcpy(&temp_message, buf, sizeof(temp_message));
if(temp_message.type == 10) {
printf("Created Chatroom\n");
}
else if(temp_message.type == 11){
connectChat(temp_message.length, host_name, chat_socket);
fflush(stdin);
}
else if(temp_message.type == 15) {
printf("Chatroom exits. Type join <Room_name> to join\n");
}
}
}
}
}
close(chat_socket);
return 0;
}
I gave both sets of code just in case it was need. The program is designed to create multiple chat rooms.
invalid argument is the EINVAL error code, which in the context of connect() means:
An invalid argument was detected (e.g., address_len is not valid for the address family, the specified address family is invalid).
You have multiple calls to connect() in your client code (why?), but you did not indicate which call is the one that is failing. In connectChat() at least, sizeof(struct sockaddr) should be sizeof(struct sockaddr_in) instead, or better sizeof(sock), like you do in main().
Also, if either connect() fails, you are leaking the socket returned by socket(). You need to close() it.
Also, gethostbyname() is deprecated, you should be using getaddrinfo() instead. You are creating IPv4 sockets, which only work with IPv4 addresses. You are not checking if gethostbyname() actually returns an IPv4 address (host_name->h_addr_type == AF_INET) before copying the address bytes into your sock variable. At least with getaddrinfo(), you can restrict the output to IPv4 addresses only. You don't have that option with gethostbyname().
Since you're looking for a way to figure out your error, I'll suggest you to use the following Makefile:
CFLAGS=-Wall -g -O2
CC=gcc
LDFLAGS=-lpthread
all: Server Client
Server: Server.c
Client: Client.c
After running make command you'll see a lot of warnings. Some of them:
Server.c: In function ‘createResponse’:
Server.c:81:5: warning: ignoring return value of ‘write’, declared with attribute warn_unused_result [-Wunused-result]
write(chat_socket, temp_buff, MSG_SIZE);
^
Server.c: In function ‘chat_room_main’:
Server.c:237:25: warning: ‘chat_socket’ may be used uninitialized in this function [-Wmaybe-uninitialized]
close(chat_socket);
^
Server.c: In function ‘main’:
Server.c:319:36: warning: array subscript is above array bounds [-Warray-bounds]
msg_buf[19]= 0;
Client.c: In function ‘connectChat’:
Client.c:113:20: warning: passing argument 1 of ‘memset’ makes pointer from integer without a cast
memset(temp, 0, sizeof(buf));
^
So just try to fix these warnings. I mean all of them.

"BUG: scheduling while atomic" in a simple custom module

I wrote a simple module which emulates a force feedback input device so that I can test the underlying FFB implementation. However, the module sometimes crashes the kernel with the "scheduling while atomic" message. According to the backtrace the crash is triggered by ff_dummy_open() and I can reproduce it easily by destroying and recreating the dummy device a couple of times in a row through sysfs. What am I doing wrong?
Source of the module:
#include <linux/input.h>
#include <linux/module.h>
#include <linux/mutex.h>
#include <linux/slab.h>
#include <linux/sysfs.h>
#include <linux/input/ff-logitech.h>
MODULE_LICENSE("GPL");
struct ff_dummy_device {
struct input_dev *dev;
int slot;
};
static struct kobject *ff_dummy_kobj;
static struct ff_dummy_device **ff_dummy_devices;
static int max_device_count;
static unsigned char device_count = 0;
static struct mutex mtx;
static const char *ff_dummy_name = "DumFFBD";
static const signed short ff_dummy_effects[] = {
FF_CONSTANT,
FF_PERIODIC,
FF_TRIANGLE,
FF_SAW_UP,
FF_SAW_DOWN,
FF_SINE,
FF_SQUARE,
FF_SPRING,
FF_DAMPER,
FF_INERTIA,
FF_FRICTION,
FF_RAMP,
-1
};
static int ff_dummy_control(struct input_dev *dev, void *data, const struct lgff_effect_command *command)
{
struct ff_dummy_device *ddev = data;
switch (command->cmd) {
case LGFF_START_COMBINED:
pr_debug("Force X: %d, Force Y: %d, (idx %d)\n", command->u.simple_force.x, command->u.simple_force.y, ddev->slot);
break;
case LGFF_STOP_COMBINED:
pr_debug("Stopping COMBINED effect (idx %d).\n", ddev->slot);
break;
case LGFF_START_UNCOMB:
pr_debug("Starting UNCOMBINABLE effect.\n");
pr_debug("LC(x): %d RC(x): %d, LS(x): %d, RS(x): %d\n",
command->u.uncomb.effect->u.condition[0].left_coeff,
command->u.uncomb.effect->u.condition[0].right_coeff,
command->u.uncomb.effect->u.condition[0].left_saturation,
command->u.uncomb.effect->u.condition[0].right_saturation);
pr_debug("LC(y): %d RC(y): %d, LS(y): %d, RS(y): %d\n",
command->u.uncomb.effect->u.condition[1].left_coeff,
command->u.uncomb.effect->u.condition[1].right_coeff,
command->u.uncomb.effect->u.condition[1].left_saturation,
command->u.uncomb.effect->u.condition[1].right_saturation);
switch (command->u.uncomb.effect->type) {
case FF_DAMPER:
pr_debug("Starting DAMPER id %d\n", command->u.uncomb.id);
break;
case FF_FRICTION:
pr_debug("Starting FRICTION id %d\n", command->u.uncomb.id);
break;
case FF_INERTIA:
pr_debug("Starting INERTIA id %d\n", command->u.uncomb.id);
break;
case FF_SPRING:
pr_debug("Starting SPRING id %d\n", command->u.uncomb.id);
break;
}
break;
case LGFF_STOP_UNCOMB:
pr_debug("Stopping UNCOMBINABLE effect.\n");
switch (command->u.uncomb.effect->type) {
case FF_DAMPER:
pr_debug("Stopping DAMPER id %d\n", command->u.uncomb.id);
break;
case FF_FRICTION:
pr_debug("Stopping FRICTION id %d\n", command->u.uncomb.id);
break;
case FF_INERTIA:
pr_debug("Stopping INERTIA id %d\n", command->u.uncomb.id);
break;
case FF_SPRING:
pr_debug("Stopping SPRING id %d\n", command->u.uncomb.id);
break;
}
break;
}
return 0;
}
static void ff_dummy_close(int idx)
{
if (idx < 0 || idx > max_device_count) {
printk(KERN_WARNING "Invalid device index.\n");
return;
}
if (!ff_dummy_devices[idx])
return;
mutex_lock(&mtx);
input_unregister_device(ff_dummy_devices[idx]->dev);
kfree(ff_dummy_devices[idx]);
ff_dummy_devices[idx] = NULL;
device_count--;
mutex_unlock(&mtx);
printk(KERN_NOTICE "Dummy force feedback %u device removed.\n", idx);
}
static int ff_dummy_open(int idx)
{
struct ff_dummy_device *newdummy;
struct input_dev *newdev;
int i, ret;
if (idx < 0 || idx >= max_device_count) {
printk(KERN_WARNING "Invalid device index.\n");
return -EINVAL;
}
newdummy = kzalloc(sizeof(struct ff_dummy_device *), GFP_KERNEL);
if (!newdummy) {
printk(KERN_ERR "Unable to allocate memory for dummy device slot.\n");
return -ENOMEM;
}
mutex_lock(&mtx);
if (ff_dummy_devices[idx]) {
printk(KERN_WARNING "Selected slot %u already occupied.\n", idx);
mutex_unlock(&mtx);
kfree(newdummy);
return -EINVAL;
}
ff_dummy_devices[idx] = newdummy;
newdev = input_allocate_device();
if (!newdev) {
printk(KERN_ERR "Unable to allocate memory for input device.\n");
ret = -ENOMEM;
goto open_err;
}
newdev->id.bustype = BUS_VIRTUAL;
newdev->id.vendor = 0xffff;
newdev->id.product = 0x0001;
newdev->id.version = 0x0001;
newdev->name = ff_dummy_name;
newdev->uniq = kasprintf(GFP_KERNEL, "%s_%u", ff_dummy_name, idx);
set_bit(EV_FF, newdev->evbit);
/* Make the device look like force feedback device */
for (i = 0; ff_dummy_effects[i] >= 0; i++)
set_bit(ff_dummy_effects[i], newdev->ffbit);
ret = input_register_device(newdev);
if (ret) {
printk(KERN_ERR "Unable to register dummy device.\n");
input_free_device(newdev);
goto open_err;
}
ret = input_ff_create_logitech(newdev, (void *)ff_dummy_devices[idx], ff_dummy_control);
if (ret) {
printk(KERN_ERR "Unable to register dummy device with ff-logitech\n");
input_unregister_device(newdev);
goto open_err;
}
ff_dummy_devices[idx]->dev = newdev;
ff_dummy_devices[idx]->slot = idx;
device_count++;
mutex_unlock(&mtx);
printk(KERN_NOTICE "Dummy force feedback %u device created.\n", idx);
return 0;
open_err:
kfree(ff_dummy_devices[idx]);
ff_dummy_devices[idx] = NULL;
mutex_unlock(&mtx);
return ret;
}
static ssize_t ff_dummy_add_device_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
{
int ret;
mutex_lock(&mtx);
ret = scnprintf(buf, PAGE_SIZE, "%u\n", device_count);
mutex_unlock(&mtx);
return ret;
}
static ssize_t ff_dummy_add_device_store(struct kobject *kobj, struct kobj_attribute *attr, const char *buf,
size_t count)
{
int ret;
int idx = 0;
sscanf(buf, "%d", &idx);
ret = ff_dummy_open(idx);
if (ret) {
printk(KERN_ERR "Dummy device creation failed with errno %d\n", ret);
return ret;
}
return count;
}
static ssize_t ff_dummy_del_device_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
{
int i;
int ret = 0;
mutex_lock(&mtx);
for (i = 0; i < max_device_count; i++) {
if (ff_dummy_devices[i])
ret += scnprintf(buf + ret, PAGE_SIZE, "[%u] ", i);
else
ret += scnprintf(buf + ret, PAGE_SIZE, "%u ", i);
}
mutex_unlock(&mtx);
ret += scnprintf(buf + ret, PAGE_SIZE, "\n");
return ret;
}
static ssize_t ff_dummy_del_device_store(struct kobject *kobj, struct kobj_attribute *attr, const char *buf,
size_t count)
{
int idx = 0;
sscanf(buf, "%d", &idx);
ff_dummy_close(idx);
return count;
}
static struct kobj_attribute add_device_attr =
__ATTR(add_device, 0644, ff_dummy_add_device_show, ff_dummy_add_device_store);
static struct kobj_attribute del_device_attr =
__ATTR(del_device, 0644, ff_dummy_del_device_show, ff_dummy_del_device_store);
static struct attribute *attrs[] = {
&add_device_attr.attr,
&del_device_attr.attr,
NULL
};
static struct attribute_group attrs_grp = {
.attrs = attrs
};
static void __exit ff_dummy_exit(void)
{
int i;
sysfs_remove_group(ff_dummy_kobj, &attrs_grp);
for (i = 0; i < max_device_count; i++)
if (ff_dummy_devices[i])
ff_dummy_close(i);
kfree(ff_dummy_devices);
kobject_put(ff_dummy_kobj);
printk(KERN_NOTICE "Dummy force feedback module removed.\n");
}
static int __init ff_dummy_init(void)
{
int ret;
if (max_device_count < 1)
max_device_count = 2;
ff_dummy_kobj = kobject_create_and_add("ff_dummy_device_obj", kernel_kobj);
if (!ff_dummy_kobj)
return -ENOMEM;
ff_dummy_devices = kcalloc(max_device_count, sizeof(struct ff_dummy_device *), GFP_KERNEL);
if (!ff_dummy_devices) {
ret = -ENOMEM;
goto err_alloc;
}
mutex_init(&mtx);
ret = sysfs_create_group(ff_dummy_kobj, &attrs_grp);
if (ret)
goto err_sysfs;
ret = ff_dummy_open(0);
if (ret)
goto err_open;
printk(KERN_NOTICE "Dummy force feedback module loaded.\n");
return 0;
err_open:
sysfs_remove_group(ff_dummy_kobj, &attrs_grp);
err_sysfs:
kfree(ff_dummy_devices);
err_alloc:
kobject_put(ff_dummy_kobj);
return ret;
}
module_param_named(max_device_count, max_device_count, int, S_IRUGO);
MODULE_PARM_DESC(max_device_count, "Maximum number of dummy devices that can be created simultaneously.");
module_exit(ff_dummy_exit);
module_init(ff_dummy_init);
EDIT:
The scheduling problem might have been a false lead. The only thing I am certain about is that the crash happens deep inside input_register_device(). "in_atomic()" and "in_interrupt()" return 0.
EDIT:
Solved. The actual bug was caused by a double free error in the underlying ff-logitech module and incorrect allocation of "struct ff_dummy_device *" instead of "struct ff_dummy_device".

How to write a Hello World iWarp application?

I am trying to write a small program demonstrating Remote DMA over iWarp. I have the softiwarp Linux kernel module loaded and the userspace library compiled.
I am looking for documentation or sample code that explains setting up a connection and, e.g., sending a simple data block to the remote end ("Hello World!") to get me started, yet all I can find is the OpenFabrics' training web site, which is not helpful at all.
#include <arpa/inet.h>
#include <string.h>
#include <stdio.h>
#include <errno.h>
#include <getopt.h>
#include <stdlib.h>
#include <unistd.h>
#include <rdma/rdma_cma.h>
struct Args {
char *remote_addr;
int is_server;
int port;
};
struct Args args;
int main(int argc, char *argv[])
{
struct rdma_event_channel *evch;
struct rdma_cm_id *server_id;
struct rdma_cm_id *client_id;
struct rdma_cm_event *event;
struct rdma_conn_param conn_param;
struct ibv_pd *pd;
struct ibv_cq *cq;
struct ibv_mr *mr;
struct ibv_send_wr snd_wr;
struct ibv_recv_wr rcv_wr;
struct ibv_sge sge;
struct ibv_wc wc;
struct ibv_qp_init_attr attr = {
.cap = {
.max_send_wr = 32,
.max_recv_wr = 32,
.max_send_sge = 1,
.max_recv_sge = 1,
.max_inline_data = 64
},
.qp_type = IBV_QPT_RC
};
char msg[256] = "Hello World";
int msg_len = strlen(msg) + 1;
struct sockaddr_in sin;
args.remote_addr = "0.0.0.0";
args.is_server = 1;
args.port = 21234;
/* Parameter parsing. */
while (1) {
int c;
c = getopt(argc, argv, "c:p:");
if (c == -1)
break;
switch (c) {
case 'c':
args.is_server = 0;
args.remote_addr = optarg;
break;
case 'p':
args.port = strtol(optarg, NULL, 0);
break;
default:
perror("Invalid option");
exit(-1);
};
}
if (args.is_server) {
if (!(evch = rdma_create_event_channel())) {
perror("rdma_create_event_channel");
exit(-1);
}
if (rdma_create_id(evch, &server_id, NULL, RDMA_PS_TCP)) {
perror("rdma_create_id");
exit(-1);
}
sin.sin_family = AF_INET;
sin.sin_port = htons(args.port);
sin.sin_addr.s_addr = htonl(INADDR_ANY);
if (rdma_bind_addr(server_id, (struct sockaddr *)&sin)) {
perror("rdma_bind_addr");
exit(-1);
}
if (rdma_listen(server_id, 6)) {
perror("rdma_listen");
exit(-1);
}
if (rdma_get_cm_event(evch, &event)
|| event->event != RDMA_CM_EVENT_CONNECT_REQUEST) {
perror("rdma_get_cm_event");
exit(-1);
}
client_id = (struct rdma_cm_id *)event->id;
if (!(pd = ibv_alloc_pd(client_id->verbs))) {
perror("ibv_alloc_pd");
exit(-1);
}
if (!(mr = ibv_reg_mr(pd, msg, 256,
IBV_ACCESS_REMOTE_WRITE |
IBV_ACCESS_LOCAL_WRITE |
IBV_ACCESS_REMOTE_READ))) {
perror("ibv_reg_mr");
exit(-1);
}
if (!(cq = ibv_create_cq(client_id->verbs, 32, 0, 0, 0))) {
perror("ibv_create_cq");
exit(-1);
}
attr.send_cq = attr.recv_cq = cq;
if (rdma_create_qp(client_id, pd, &attr)) {
perror("rdma_create_qp");
exit(-1);
}
memset(&conn_param, 0, sizeof conn_param);
if (rdma_accept(client_id, &conn_param)) {
perror("rdma_accept");
exit(-1);
}
rdma_ack_cm_event(event);
if (rdma_get_cm_event(evch, &event)
|| event->event != RDMA_CM_EVENT_ESTABLISHED) {
perror("rdma_get_cm_event");
exit(-1);
}
rdma_ack_cm_event(event);
sge.addr = (uint64_t)msg;
sge.length = msg_len;
sge.lkey = mr->lkey;
snd_wr.sg_list = &sge;
snd_wr.num_sge = 1;
snd_wr.opcode = IBV_WR_SEND;
snd_wr.send_flags = IBV_SEND_SIGNALED;
snd_wr.next = NULL;
if (ibv_post_send(client_id->qp, &snd_wr, NULL)) {
perror("ibv_post_send");
exit(-1);
}
while (!ibv_poll_cq(cq, 1, &wc))
;
if (wc.status != IBV_WC_SUCCESS) {
perror("ibv_poll_cq");
exit(-1);
}
}
else {
if (!(evch = rdma_create_event_channel())) {
perror("rdma_create_event_channel");
exit(-1);
}
if (rdma_create_id(evch, &client_id, NULL, RDMA_PS_TCP)) {
perror("rdma_create_id");
exit(-1);
}
sin.sin_family = AF_INET;
sin.sin_port = htons(args.port);
sin.sin_addr.s_addr = inet_addr(args.remote_addr);
if (rdma_resolve_addr
(client_id, NULL, (struct sockaddr *)&sin, 2000)) {
perror("rdma_resolve_addr");
exit(-1);
}
if (rdma_get_cm_event(evch, &event)
|| event->event != RDMA_CM_EVENT_ADDR_RESOLVED) {
perror("rdma_get_cm_event");
exit(-1);
}
rdma_ack_cm_event(event);
if (rdma_resolve_route(client_id, 2000)) {
perror("rdma_resolve_route");
exit(-1);
}
if (rdma_get_cm_event(evch, &event)
|| event->event != RDMA_CM_EVENT_ROUTE_RESOLVED) {
perror("rdma_get_cm_event");
exit(-1);
}
rdma_ack_cm_event(event);
if (!(pd = ibv_alloc_pd(client_id->verbs))) {
perror("ibv_alloc_pd");
exit(-1);
}
if (!(mr = ibv_reg_mr(pd, msg, 256,
IBV_ACCESS_REMOTE_WRITE |
IBV_ACCESS_LOCAL_WRITE |
IBV_ACCESS_REMOTE_READ))) {
perror("ibv_reg_mr");
exit(-1);
}
if (!(cq = ibv_create_cq(client_id->verbs, 32, 0, 0, 0))) {
perror("ibv_create_cq");
exit(-1);
}
attr.send_cq = attr.recv_cq = cq;
if (rdma_create_qp(client_id, pd, &attr)) {
perror("rdma_create_qp");
exit(-1);
}
sge.addr = (uint64_t)msg;
sge.length = msg_len;
sge.lkey = mr->lkey;
rcv_wr.sg_list = &sge;
rcv_wr.num_sge = 1;
rcv_wr.next = NULL;
if (ibv_post_recv(client_id->qp, &rcv_wr, NULL)) {
perror("ibv_post_recv");
exit(-1);
}
memset(&conn_param, 0, sizeof conn_param);
if (rdma_connect(client_id, &conn_param)) {
perror("rdma_connect");
exit(-1);
}
if (rdma_get_cm_event(evch, &event)
|| event->event != RDMA_CM_EVENT_ESTABLISHED) {
perror("rdma_get_cm_event");
exit(-1);
}
rdma_ack_cm_event(event);
while (!ibv_poll_cq(cq, 1, &wc)) ;
if (wc.status != IBV_WC_SUCCESS) {
perror("ibv_poll_cq");
exit(-1);
}
fprintf(stdout, "Received %s \n", msg);
}
fprintf(stdout, "Done \n");
return 0;
}
Probably the best documentation and examples are in the librdmacm source. It includes full man pages around establishing connections (actually moving data is in the libibverbs man pages), as well as a number of example programs under the examples directory. The simplest example is rping.
As the comment says, trying to code something up and then asking specific questions is more productive.

Resources