Related
I am trying to send authenticate messages to an access point, but when I do that it sends 15 authenticate messages to the AP, whereby the AP doesn't respond. I use a Mac OS X and the libpcap library.
Here is my code:
int inject(char *src_mac, char *dst_mac)
{
int i, rc;
char *device, *packet;
char error[PCAP_ERRBUF_SIZE];
pcap_t *handle;
device = pcap_lookupdev(error);
handle = pcap_create(device, error);
check(device != NULL, "Failed to find a device!");
check(handle != NULL, "Failed to create handle!");
rc = pcap_set_rfmon(handle, 1);
check(rc == 0, "Failed to set monitor mode!");
rc = pcap_set_promisc(handle, 1);
check(rc == 0, "Failed to set promiscuous mode!");
rc = pcap_activate(handle);
check(rc == 0, "Failed to activate handle!");
rc = pcap_datalink(handle);
check(rc == DLT_IEEE802_11_RADIO, "Failed to use the correct format!");
packet = radiotap_setup(src_mac, dst_mac,\
dst_mac, 0xb0);
rc = pcap_inject(handle, packet,\
RADIO_LEN + sizeof(ieee80211_hdr));
check(rc != -1, "Failed to send packet!");
pcap_close(handle);
return 1;
error:
pcap_close(handle);
return -1;
}
char *radiotap_setup(char *dst_mac, char *src_mac, char *bssid_mac, int fc)
{
int i, radio_len;
unsigned int shost_mac[6], dhost_mac[6], bhost_mac[6];
static char packet[RADIO_LEN + sizeof(ieee80211_hdr)];
ieee80211_hdr ieeeh;
ieeeh.fc = fc;
ieeeh.dur = 314;
sscanf(src_mac, "%x:%x:%x:%x:%x:%x", &shost_mac[0], &shost_mac[1],\
&shost_mac[2], &shost_mac[3], &shost_mac[4], &shost_mac[5]);
sscanf(dst_mac, "%x:%x:%x:%x:%x:%x", &dhost_mac[0], &dhost_mac[1],\
&dhost_mac[2], &dhost_mac[3], &dhost_mac[4], &dhost_mac[5]);
sscanf(bssid_mac, "%x:%x:%x:%x:%x:%x", &bhost_mac[0], &bhost_mac[1],\
&bhost_mac[2], &bhost_mac[3], &bhost_mac[4], &bhost_mac[5]);
for (i = 0; i != 6; i++) {
ieeeh.src[i] = (unsigned char)shost_mac[i];
ieeeh.dest[i] = (unsigned char)dhost_mac[i];
ieeeh.bssid[i] = (unsigned char)bhost_mac[i];
}
ieeeh.seq = rand();
ieeeh.rc = 1792;
radio_len = RADIO_LEN;
memcpy(&packet[2], &radio_len, 2);
memcpy(packet + RADIO_LEN, &ieeeh,\
sizeof(ieee80211_hdr));
return packet;
}
When I execute the code I get this on Wireshark:
Wireshark output
I have created a client-server file sharing system with multi threading. The client code is working correctly for a single client. When I increase the number of threads in client, segmentation fault is occurred in server code.
When I executed the code on gdb, it shows the error segmentation fault occurred, no such file or directory. Is this because of the threads sharing file descriptor? How to resolve the segmentation fault?
----------edit-----------
I considered all your suggestions. Most of the errors are resolved, but when I try to send a >10mb file, some send-recv call does not execute fully while sending it out with threads(It works fine with a single thread). I believe this is the reason memory leakage is happening and ultimately results in segmentation fault(file pointers not closed). The same is happening in gdb.
How to resolve this send receive blocking error?
client code
#include <time.h>
#include<arpa/inet.h>
#include<sys/socket.h>
#include<sys/types.h>
#include<netinet/in.h>
#include<string.h>
#include<stdio.h>
#include <stdlib.h>
#include<pthread.h>
#include <semaphore.h>
#define PORT 8029
#define SIZE 1024
#define SERVER_ADDR "192.168.43.158" //"10.15.36.112"
//defining number of threads
struct ser_data
{
int sockfd;
int n;
};
void *client_req(void * data){
// printf("inside thread\n");
//sleep(1);
int s,c,n,read_size,r;
//login_id and password of the user
//array to choose file names randomly
//char f_name[20][20]={"f0.txt","f1.txt","f2.txt","f3.txt","f4.txt","f5.txt","f6.txt","f7.txt","f8.txt","f9.txt","f10.txt\0","f11.txt\0","f12.txt\0" ,"f13.txt\0","f14.txt\0","f15.txt\0","f16.txt\0","f17.txt\0","f18.txt","f19.txt"};
//socket address for client and server
//used for generation of random no
time_t t;
struct sockaddr_in cli,serv;
FILE *f;
char fname[SIZE]="file_cli/";
char f_name[SIZE];
char login_id[21], pswd[21], choice[2];
//msg_cli_rec= message recieved form server
char msg_cli_rec[SIZE];
//msg_cli_send =message sent by client
char msg_cli_send[SIZE];
time_t start, stop;
int brk=0;
start = time(NULL);
s=socket(AF_INET,SOCK_STREAM,0);
bzero((char*)&serv,sizeof(cli));
cli.sin_family=AF_INET;
cli.sin_port=htons(PORT);
cli.sin_addr.s_addr = inet_addr(SERVER_ADDR);
connect(s,(struct sockaddr*)&cli,sizeof(cli));
//printf("\nConnected with server");
strcpy(choice, "1");
/*msg_cli_rec = (char *) malloc(1000* sizeof(char));
msg_cli_send = (char *) malloc(1000* sizeof(char));*/
//if user wants to login
if(strcmp(choice,"1")==0)
{
strcpy(login_id, "prach");
send(s, login_id, sizeof(login_id), 0);
strcpy(pswd, "prach");
send(s, pswd, sizeof(pswd), 0);
}
//making default choice download 1
do {
strcpy(choice, "1\0");
strcpy(msg_cli_send, choice);
//send(s, choice, sizeof(choice), 0);
send(s,msg_cli_send,sizeof(msg_cli_send),0);
//random number generation
srand((unsigned) time(NULL));
//r=((unsigned)rand()*(i++))%20;
r=15;
if(strcmp(choice,"1")==0)
{
/*if(recv(s, msg_cli_rec, sizeof(msg_cli_rec), 0))
{
//if((strcmp("end",msg_cli_rec))==0)break;
printf("\n%s", msg_cli_rec);
}*/
/*printf("\nEnter the file name you want:");
scanf("%s", msg_cli_send);*/
// to select file name with index of the random number
sprintf(f_name,"file (%d).txt",r);
strcpy(msg_cli_send, "");
strcpy(msg_cli_send,f_name);
// printf("\n%s",msg_cli_send);
// printf("\n rand =%d\n", r );
send(s,msg_cli_send,sizeof(msg_cli_send),0);
// printf("\nThe received file content is:");
//receiving the file names
f = fopen(strcat(fname,f_name),"w");
bzero( msg_cli_rec, sizeof(msg_cli_rec));
while((recv(s, msg_cli_rec, sizeof(msg_cli_rec), 0)> 0)&&(*msg_cli_rec!='\0'))
{//fflush(stdout);
if((strcmp("quit",msg_cli_rec))==0)break;
fprintf(f, "%s", msg_cli_rec);
//printf("\n%s", msg_cli_rec);
bzero( msg_cli_rec, sizeof(msg_cli_rec));
}
// printf("File recieved");
fclose(f);
strcpy(fname,"\0" );
//sem_post(&sem);
}
stop = time(NULL);
// printf("\n%s\n", ctime(&stop));
//printf("%ld", (stop-start));
//set the timer to 300 seconds
}while(*choice == '1' && (stop-start)<10);
//tell the server that we are done with sending files
strcpy(choice, "0");
send(s, choice, sizeof(choice), 0);
printf("%ld\n", (stop-start) );
/* free(msg_cli_rec);
free(msg_cli_send);*/
close(s);
//pthread_exit(NULL);
}
int main()
{
int N_Threads=2, count =0;
struct ser_data data;
/*while(N_Threads<=2)
{
pthread_t t;
pthread_create( &t , NULL , client_req , NULL);
N_Threads++;
if ( ! pthread_detach(t) )
printf("Thread detached successfully !!!\n");
//pthread_join(t, NULL);
}*/
while(count != N_Threads){
pthread_t handle;
count = count+1;
data.sockfd = count;
if(pthread_create(&handle, NULL, client_req,(void *)&data)<0)
error("Error creating thread");
else
printf("Thread allocation successful for fd: %d\n",data.sockfd);
}
pthread_exit(NULL);
}
server code
#include <time.h>
#include<arpa/inet.h>
#include<sys/socket.h>
#include<sys/types.h>
#include<netinet/in.h>
#include<string.h>
#include<stdio.h>
#include<pthread.h>
#include<stdlib.h>
#include<dirent.h>
#include <mysql/mysql.h>
#include <semaphore.h>
#define PORT 8029
#define SIZE 1024
#define QUERY_SIZE 200
#define N_Threads 5
#define SERV_ADDR "192.168.43.158"
clock_t start, stop;
//login id and password of the user
int file_id=1;
/*Database variables*/
MYSQL *db_conn;
char *db_server = "localhost";
char *db_user = "root";
char *db_password = "root";
char *database = "file_db";
//for synchronization while accessing the db
sem_t sem;
/* A function which generates the and returns login query statement*/
char* query_login(char *query, char *login_id, char *pswd)
{
//generating query
strcpy(query,"SELECT * FROM user_info WHERE user_id='");
strcat(query, login_id);
strcat(query, "' AND pswd='");
strcat(query, pswd);
strcat(query, "'");
return query;
}
/* A function which generates and returns the register query statement*/
char* query_register(char *query, char *login_id, char *pswd)
{
strcpy(query, "INSERT INTO user_info VALUES ( '");
strcat(query, login_id);
strcat(query, "', '");
strcat(query, pswd);
strcat(query, "' )");
return query;
}
void *connect_client(void *socket)
{ int sock=*(int*)socket;
printf("\nFD %d",sock);
char msg_c_r[SIZE], msg_s_s[SIZE];
//for the choice given to the user to login or register
char choice='0';
char msg_serv_send[SIZE],msg_serv_rec[SIZE];
char msg_cli_rec[SIZE];
char fpath[SIZE] = "file_serv/";
char fname[SIZE];
int read_size;
int num_fields=0;
char * line = NULL;
size_t len = 0;
ssize_t read;
MYSQL_ROW row;
MYSQL_RES *db_res;
char login_id[21], pswd[21];
FILE *f;
FILE *fc;
char name[SIZE];
char query1[SIZE];
char query[QUERY_SIZE];
/*locking the database for mutual exclusion*/
//sem_wait(&sem);
//executing a query
choice = '1';
strcpy(query, "\0");
switch(choice)
{
//1 = login
case '1':
/*to find the login id and password of the user*/
bzero(login_id, sizeof(login_id));
recv(sock, login_id, sizeof(login_id), 0);
bzero(pswd, sizeof(pswd));
recv(sock, pswd, sizeof(pswd), 0);
printf("The login id is: %s\nThe Password is: %s\n", login_id, pswd);
//lock for accessing db in mutual exclusion
sem_wait(&sem);
query_login(query, login_id, pswd);
//checking the details given by client
if (mysql_query(db_conn, query)!=0) {
fprintf(stderr, "%s\n", mysql_error(db_conn));
}
strcpy(query, "\0");
strcat(query,"select * from user_info where user_id='");
strcat(query,login_id);
strcat(query,"'");
mysql_query(db_conn, query);
db_res = mysql_store_result(db_conn);
row = mysql_fetch_row(db_res);
if (row!=0) {
//send(sock,"T",sizeof("T"),0);
printf("\nT");
}
//freeing the result variable so it can be used further
mysql_free_result(db_res);
//release lock
sem_post(&sem);
break;
}//switch case
/*send(sock, "\nPlease enter your choice \n 1- File Download \n 2-File Upload\n 3-Rating\n", sizeof("\nPlease enter your choice \n 1- File Download \n 2-File Upload\n 3-Rating\n"), 0);*/
int nu=1;
do{
bzero(msg_serv_rec,sizeof(msg_serv_rec));
if(recv(sock, msg_serv_rec,sizeof(msg_serv_rec), 0)>0)
{
choice = msg_serv_rec ? *msg_serv_rec : '0';
printf("\n choice = %c\n", choice);
strcpy(query, "\0");
//printf("Client's choice is file Download\n" );
/*Sending File to the client line by line
checking the database connection*/
if(choice == '1'){
/*if(mysql_query(db_conn, "SELECT name FROM file_info")==0)
{
db_res = mysql_store_result(db_conn);
num_fields = mysql_num_fields(db_res);
if(num_fields>0)
{
while ((row = mysql_fetch_row(db_res)))
{
for(int i = 0; i < num_fields; i++)
{
char *fname1=row[i] ? row[i] : "NULL";
strcat(name,fname1);
strcat(name, "\n");
//send(sock,name,sizeof(name),0);
//printf("\n%s",name);
}
}
//sending list of all files to client
send(sock,name,sizeof(name),0);*/
/*emptying the name!!
strcpy(name, "");*/
//freeing the result variable so it can be used further
/*mysql_free_result(db_res);
sem_post(&sem);*/
bzero(msg_serv_rec,sizeof(msg_serv_rec));
if(recv(sock, msg_serv_rec,sizeof(msg_serv_rec), 0)>0)
{//which file recieved
printf("%s\n", msg_serv_rec );
// sem_wait(&sem);
f = fopen(strcat(fpath, msg_serv_rec),"r");
while(fgets(msg_serv_send, sizeof(msg_serv_send), f) !=NULL)
{
if((*msg_serv_send!=EOF || *msg_serv_send!='\n'))
{
send(sock, msg_serv_send, sizeof(msg_serv_send), 0);
//printf("\n%s", msg_serv_send);
}
else
break;
}
send(sock,"quit",sizeof("quit"),0);
fclose(f);
strcpy(fpath, "file_serv/");
//sem_post(&sem);
printf("\nFile sent to the client\n");
}
}
else if (choice == '0')
break;
strcpy(msg_serv_rec, "");
//stop = clock();
//time(NULL);
}
else
{
choice = '0';
}
}while ( choice != 'f' && choice != '0');
nu++;
/* unblocking the semaphores to allow other threads to access*/
//sem_post(&sem);
if(read_size == 0)
{
puts("\nClient disconnected\n");
fflush(stdout);
}
/*else if(read_size == -1)
{perror("recv failed");}
fclose(f);*/
close(sock);
pthread_exit(NULL);
}
int main()
{ int s,n,i, clilen;
int c;
int newsockfd;
int *new_sock;
start = clock();
//pthread_t handle;
struct sockaddr_in cli,serv;//socket address for client and server
MYSQL_ROW row;
MYSQL_RES *db_res;
//initializing the semaphore
sem_init(&sem, 0, 1);
//synchronization in DB
sem_wait(&sem);
/*Database connectivity*/
db_conn = mysql_init(NULL);
/* Connect to database */
if (!mysql_real_connect(db_conn, db_server, db_user, db_password, database, 0, NULL, 0)) {
fprintf(stderr, "%s\n", mysql_error(db_conn));
exit(1);
}
/* send SQL query */
if (mysql_query(db_conn, "show tables")) {
fprintf(stderr, "%s\n", mysql_error(db_conn));
exit(1);
}
db_res = mysql_use_result(db_conn);
/* output table name */
printf("MySQL Tables in mysql database:\n");
while ((row = mysql_fetch_row(db_res)) != NULL)
printf("%s \n", row[0]);
//freeing the result variable so it can be used further
mysql_free_result(db_res);
sem_post(&sem);
//Server socket
s=socket(AF_INET,SOCK_STREAM,0);
bzero((char*)&serv,sizeof(serv));
serv.sin_family=AF_INET;
serv.sin_port=htons(PORT);
serv.sin_addr.s_addr=inet_addr( SERV_ADDR);//"10.15.36.112");
/*printf("\nServer is waiting for client to respond");
i=0*/
//accept the incomming connections from client
bind(s,(struct sockaddr *)&serv,sizeof(serv));
printf("\nAddress bind successful");
listen(s,3000);//4 is the limit of the number of outstanding connections
n=sizeof(cli);
/*
i=0;
//accept the incomming connections from client
while( (c = accept(s, (struct sockaddr *)&cli, (socklen_t*)&n))) //&& (stop-start)<300 )
{ puts("Connection accepted\n");
pthread_t t;
printf("sock =%d\n", c);
if( pthread_create( &t , NULL , connect_client , (void*) c) < 0)
{
perror("could not create thread");
return 1;
}
i++;
/*Now detach the thread ,When a detached thread terminates, its resources are
automatically released back to the system without the need for
another thread to join with the terminated thread.*/
/* if ( ! pthread_detach(t) )
printf("Thread detached successfully !!!\n");
puts("Handler assigned");
stop = clock();
}*/
clilen=sizeof(cli);
while(newsockfd = accept(s, (struct sockaddr *) &cli, &clilen))
{
if(newsockfd < 0)
error("ERROR on accept");
else{
pthread_t handle;
new_sock = malloc(1);
*new_sock = newsockfd;
if(pthread_create(&handle, NULL,connect_client ,(void *)new_sock)<0)
error("Error creating thread");
else
printf("Thread fd: %d\n",newsockfd);
if ( ! pthread_detach(handle) )
printf("Thread detached successfully !!!\n");
}
}
/* close database connection */
mysql_free_result(db_res);
mysql_close(db_conn);
close(s);
/*destroying the mutex */
sem_destroy(&sem);
return 0;
}
[EDIT]I added all my main code and some of the external functions used by this code. The code is quite long, but in summary it sends a message to a device measuring some parameters of the water in a container, and the device responds with the corresponding value measured by the sensor.
After that the code uses this value to modify the level and temperature of water. Prints the current status of the container and makes a log.txt file.[/Edit]
I want to do a constructor object-oriented-like function in C, but the address of my structure and its members are not being changed after I malloc() them. I saw this answer Changing address contained by pointer using function and I got an idea of what my problem is, but still can't solve it.
Below is my code that is doing the constructor:
udp.c
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include "udp.h"
#define BUF_SIZE 1000
#define HEADER_SIZE
typedef struct{
int socket;
char header[4];
float *send_value;
char *message_buffer;
}message;
void build_message(message **msg, int socket, char header[], float *send_value){
*msg = (message *)malloc(sizeof(message));
(*msg)->socket = socket;
strncpy((*msg)->header, header, 4);
(*msg)->send_value = send_value;
(*msg)->message_buffer = NULL;
(*msg)->message_buffer = malloc(BUF_SIZE);
//(**msg).message_buffer = (char *)(msg+sizeof(int) + sizeof(float *) + sizeof(char *)*3);
}
int prepara_socket_cliente(char *host, char *porta)
{
struct addrinfo hints;
struct addrinfo *result, *rp;
int sfd, s;
/* Obtain address(es) matching host/port */
memset(&hints, 0, sizeof(struct addrinfo));
hints.ai_family = AF_UNSPEC; /* Allow IPv4/ or IPv6 */
hints.ai_socktype = SOCK_DGRAM; /* Datagram socket */
hints.ai_flags = 0;
hints.ai_protocol = 0; /* Any protocol */
s = getaddrinfo(host, porta, &hints, &result);
if (s != 0) {
fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(s));
exit(EXIT_FAILURE);
}
/* getaddrinfo() returns a list of address structures.
Try each address until we successfully connect(2).
If socket(2) (or connect(2)) fails, we (close the socket
and) try the next address. */
for( rp = result; rp != NULL; rp = rp->ai_next) {
sfd = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);
if (sfd == -1)
continue;
if (connect(sfd, rp->ai_addr, rp->ai_addrlen) != -1)
break; /* Success */
close(sfd);
}
if (rp == NULL) { /* No address succeeded */
fprintf(stderr, "Could not connect\n");
exit(EXIT_FAILURE);
}
freeaddrinfo(result); /* No longer needed */
return sfd;
}
float receive_message(message *msg){
ssize_t nread;
int len;
//sprintf(msg->message_buffer, "%s0.0", msg->header);
len = strlen(msg->message_buffer)+1;
int rc;
if (len + 1 > BUF_SIZE){
fprintf(stderr, "Ignoring long message in argument\n");
exit(EXIT_FAILURE);
}
if((rc = write(msg->socket, msg->message_buffer, len)) != len){
printf("%d, %d\n", len, rc);
fprintf(stderr, "partial/failed write\n");
exit(EXIT_FAILURE);
}
nread = read(msg->socket, msg->message_buffer, BUF_SIZE);
if (nread == -1){
perror("read");
exit(EXIT_FAILURE);
}
return atof(msg->message_buffer+3);
}
int send_message(message *msg){
ssize_t nread;
int len;
//sprintf(msg->message_buffer, "%s%.1f", msg->header, *msg->send_value);
len = strlen(msg->message_buffer)+1;
int rc;
if (len + 1 > BUF_SIZE){
fprintf(stderr, "Ignoring long message in argument\n");
exit(EXIT_FAILURE);
}
if((rc = write(msg->socket, msg->message_buffer, len)) != len){
printf("%d, %d\n", len, rc);
fprintf(stderr, "partial/failed write\n");
exit(EXIT_FAILURE);
}
nread = read(msg->socket, msg->message_buffer, BUF_SIZE);
if (nread == -1){
perror("read");
exit(EXIT_FAILURE);
}
return 0;
}
main.c
#include<pthread.h>
#include<stdio.h>
#include<errno.h>
#include<stdlib.h>
#include<string.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<netdb.h>
#include<unistd.h>
#include<math.h>
#include<time.h>
#include<termios.h>
#include"controller.h"
#include"screen.h"
#include"myIO.h"
#include"my_time.h"
#include"data_structures.h"
#include"udp.h"
#define NUM_THREADS 5
#define MAX_PARAM_SIZE 20
#define MAX_BUFFER_SIZE 1200
//variables
typedef enum {IDLE, QUIT, CHANGE_LEVEL_REF, CHANGE_TEMP_REF} command_type;
struct timespec t1;
struct timespec t2;
pthread_cond_t screen = PTHREAD_COND_INITIALIZER;
pthread_cond_t cmd = PTHREAD_COND_INITIALIZER;
pthread_cond_t barrier = PTHREAD_COND_INITIALIZER;
int count[2] = {0,0};
command_type command = IDLE;
double_buffer* log_buffer;
char* port = NULL;
char* host = NULL;;
int socket_cliente;
real Ta, Ti, No;
real T=0;
real H=0;
real Q=0;
real Nf=0;
real Ni=0;
real Na=0;
real href = 2.0;
real tref = 25.0;
pthread_mutex_t em_scan;
pthread_mutex_t em;
void init(){
port = (char *)malloc(sizeof(char)*MAX_PARAM_SIZE);
host = (char *)malloc(sizeof(char)*MAX_PARAM_SIZE);
log_buffer = build_double_buffer();
}
//threads
void *LevelControl(void *threadid){
/**********************************************************
*thread responsible for controling the water level
*********************************************************/
controller* levelControl = NULL;
levelControl = build_controller();
levelControl->kp = 10000.0;
levelControl->ki = 0.0;
levelControl->kd = 0.0;
levelControl->error_thresh = 1.0;
levelControl->step_time = 0.7;
levelControl->max_actuator_value = 100.0;
levelControl->min_actuator_value = 0.0;
int intervalo = 90000000;
message *message_H = NULL;
build_message(&message_H, socket_cliente, "sh-", &H);
sprintf(message_H->message_buffer, "%s0.0", message_H->header);
message *message_Nf = NULL;
build_message(&message_Nf, socket_cliente, "anf", &Nf);
message *message_Ni = NULL;
build_message(&message_Ni, socket_cliente, "ani", &Ni);
loop_1:
if(command != QUIT){
pthread_mutex_lock(&em);
H = receive_message(message_H);
levelControl->error = href - H;
if(levelControl->error < 0.0){
levelControl->error = -levelControl->error;
Nf = PID_Update(levelControl);
Ni = 0.0;
}else{
Ni = PID_Update(levelControl);
Nf = 0.0;
}
sprintf(message_Nf->message_buffer, "%s%f", message_Nf->header, *message_Nf->send_value);
send_message(message_Nf);
sprintf(message_Ni->message_buffer, "%s%f", message_Ni->header, *message_Ni->send_value);
send_message(message_Ni);
count[1] = 1;
if((count[0] == 1) & (count[1] == 1)) pthread_cond_signal(&barrier);
next_timer(t1, intervalo);
pthread_mutex_unlock(&em);
goto loop_1;
}else return NULL;
}
void *TempControl(void *threadid){
/**********************************************************
* thread responsible for controling the temperature
*********************************************************/
controller *tempControl = NULL;
tempControl = build_controller();
tempControl->kp = 10000.0;
tempControl->ki = 0.0;
tempControl->kd = 0.0;
tempControl->error_thresh = 20.0;
tempControl->step_time = 0.7;
tempControl->max_actuator_value = 10000.0;
tempControl->min_actuator_value = 0.0;
int intervalo = 70000000;
message *message_T = NULL;
build_message(&message_T, socket_cliente, "st-", &T);
sprintf(message_T->message_buffer, "%s0.0", message_T->header);
message *message_Q = NULL;
build_message(&message_Q, socket_cliente, "aq-", &Q);
message *message_Na = NULL;
build_message(&message_Na, socket_cliente, "ana", &Na);
char *log_string = NULL;
log_string = (char *)malloc(sizeof(char)*MAX_BUFFER_SIZE);
// while(command != QUIT){
loop_2:
if(command != QUIT){
pthread_mutex_lock(&em);
T = receive_message(message_T);
tempControl->error = tref - T;
Q = PID_Update(tempControl);
sprintf(message_Q->message_buffer, "%s%f", message_Q->header, *message_Q->send_value);
send_message(message_Q);
if(Q == tempControl->max_actuator_value){
Na = 10.0;
}else if(Q == tempControl->min_actuator_value){
Na = 0.0;
}
sprintf(message_Na->message_buffer, "%s%f", message_Na->header, *message_Na->send_value);
send_message(message_Na);
count[0] = 1;
if((count[0] == 1) & (count[1] == 1)) pthread_cond_signal(&barrier);
pthread_mutex_unlock(&em);
sprintf(log_string, "Temperura: %f\n", T);
setDoubleBuffer(log_buffer, log_string);
next_timer(t2, intervalo);
goto loop_2;
}else return NULL;
// pthread_exit(NULL);
}
void *Status(void *threadid){
/**********************************************************
*thread responsible for printing the current status on
*the screen and setting tref and href
*********************************************************/
message *message_Ta = NULL;
build_message(&message_Ta, socket_cliente, "sta", &Ta);
sprintf(message_Ta->message_buffer, "%s0.0", message_Ta->header);
message *message_Ti = NULL;
build_message(&message_Ti, socket_cliente, "sti", &Ti);
sprintf(message_Ti->message_buffer, "%s0.0", message_Ti->header);
message *message_No = NULL;
build_message(&message_No, socket_cliente, "sno", &No);
sprintf(message_No->message_buffer, "%s0.0", message_No->header);
pthread_mutex_lock(&em);
while((count[0] != 1) | (count[1] != 1)) pthread_cond_wait(&barrier, &em);
pthread_mutex_unlock(&em);
//while(command != QUIT){
loop_3:
switch(command){
case IDLE:
pthread_mutex_lock(&em);
clearScreen();
Ta = receive_message(message_Ta);
Ti = receive_message(message_Ti);
No = receive_message(message_No);
printf("/********************************************************************************************************\n");
printf("*STATUS\n");
printf("*reference temperature: %f\n", tref);
printf("*reference water level: %f\n", href);
printf("*current temperature: %f\n", T);
printf("*current water level: %f\n", H);
printf("*other sensor value => Ni = %f, No = %f, Na = %f, Nf = %f, Ta = %f, Ti = %f\n", Ni, No, Na, Nf, Ta,Ti);
printf("*\n");
printf("*\n");
printf("*\n");
printf("*(q)uit, change (l)evel reference, change (t)emperature reference\n");
pthread_mutex_unlock(&em);
sleep(1);
break;
case CHANGE_LEVEL_REF:
pthread_mutex_lock(&em_scan);
printf("insert new Level reference\n");
scanf("%f", &href);
pthread_cond_signal(&screen);
while(command != IDLE){
pthread_cond_wait(&cmd, &em_scan);
}
pthread_mutex_unlock(&em_scan);
break;
case CHANGE_TEMP_REF:
pthread_mutex_lock(&em_scan);
printf("insert new Temperature reference\n");
scanf("%f", &tref);
pthread_cond_signal(&screen);
while(command != IDLE){
pthread_cond_wait(&cmd, &em_scan);
}
pthread_mutex_unlock(&em_scan);
case QUIT:
fprintf(stderr, "get saiu\n");
return NULL;
}
goto loop_3;
//return NULL;
}
void *GetReferences(void *threadid){
/**********************************************************
*thread responsible for changing the program mode
*********************************************************/
char temp;
//while(command != QUIT){
loop_4:
temp = getch();
switch(temp){
case 'q':
command = QUIT;
printf("%c\n --------------------------------------------------------\n", temp);
return NULL;
case 'l':
pthread_mutex_lock(&em_scan);
command = CHANGE_LEVEL_REF;
pthread_cond_wait(&screen, &em_scan);
command = IDLE;
pthread_cond_signal(&cmd);
pthread_mutex_unlock(&em_scan);
break;
case 't':
pthread_mutex_lock(&em_scan);
command = CHANGE_TEMP_REF;
pthread_cond_wait(&screen, &em_scan);
command = IDLE;
pthread_cond_signal(&cmd);
pthread_mutex_unlock(&em_scan);
}
goto loop_4;
}
void *Log(void *threadid){
char *receive_buffer = NULL;
receive_buffer = (char *)malloc(sizeof(char)*MAX_BUFFER_SIZE);
//while(command != QUIT){
loop_5:
if(command != QUIT){
get_buffer(receive_buffer, log_buffer);
write_log(receive_buffer);
goto loop_5;
}else return NULL;
}
int main (int argc, char *argv[]){
init();
pthread_mutex_init(&em_scan, NULL);
pthread_mutex_init(&em, NULL);
init_nano_timer(t1);
init_nano_timer(t2);
clearScreen();
printf("Enter the port where to be used in the udp communication\n");
scanf("%s", port);
strcpy(host, "localhost");
socket_cliente = prepara_socket_cliente(host, port);
pthread_t threads[NUM_THREADS];
int rc;
int t;
void *threadName[NUM_THREADS];
threadName[0] = TempControl;
threadName[1] = LevelControl;
threadName[2] = Status;
threadName[3] = GetReferences;
threadName[4] = Log;
for(t=0; t<NUM_THREADS; t++){
rc = pthread_create(&threads[t], NULL, threadName[t], (void *)t);
if(rc){
printf("ERROR; return code from pthread_create() is %d\n", rc);
exit(1);
}
}
for(t=0; t<NUM_THREADS; t++){
rc = pthread_join(threads[t], NULL);
if(rc){
printf("ERROR; return code from pthread_create() is %d\n", rc);
exit(1);
}
}
return 0;
}
Btw, I am using threads in these code, would this code be thread-safe even without mutexes?
As #Sourav Ghosh rightly commented you:
void build_message(message **msg, int socket, char header[], float *send_value)
{
*msg = malloc(sizeof(message));
(*msg)->socket = socket;
strncpy((*msg)->header, header, 4);
(*msg)->send_value = send_value;
(*msg)->message_buffer = malloc(BUF_SIZE);
}
Change the structure to:
typedef struct{
int socket;
char header[4];
float *send_value;
char *message_buffer;
}message;
I am trying to execute a command on a router via ssh. After the login, when I execute the command on the device, it asks for an additional password. I am not able to send the password using libssh2_channel_write(). Here is the code snippet (modified the ssh2_exec.c that comes with the library). This is a snippet where the device is authenticated and the command has been issued. This loop just tries to get read the output of the executed command:
for( ;; )
{
/* loop until we block */
int rc;
do
{
char buffer[0x4000];
rc = libssh2_channel_read( channel, buffer, sizeof(buffer) );
if( rc > 0 )
{
int i;
char *enable = "stic-isr2951-t1";
int ret;
bytecount += rc;
fprintf(stderr, "We read [%d] bytes:\n", bytecount);
for( i=0; i < rc; ++i )
fputc( buffer[i], stderr);
**if ( strstr(buffer, "assword:") != NULL ){
fprintf(stderr, "Sending the additional password now\n");
ret = libssh2_channel_write(channel, enable, strlen(enable));
fprintf(stderr, "Wrote [%d] bytes\n", ret);
}**
}
else {
if( rc != LIBSSH2_ERROR_EAGAIN )
/* no need to output this for the EAGAIN case */
fprintf(stderr, "libssh2_channel_read returned %d\n", rc);
}
}
while( rc > 0 );
/* this is due to blocking that would occur otherwise so we loop on
this condition */
if( rc == LIBSSH2_ERROR_EAGAIN )
{
waitsocket(sock, session);
}
else
break;
}
In the snippet above, the code that detects that the device is posting a password prompt is:
if ( strstr(buffer, "assword:") != NULL ){
fprintf(stderr, "Sending the additional password now\n");
ret = libssh2_channel_write(channel, enable, strlen(enable));
fprintf(stderr, "Wrote [%d] bytes\n", ret);
}
That's where I have a problem. The password being sent on the channel isn't working as the device continues to timeout expecting the password. There is no indication that libssh2_channel_write() failed as the return value says it wrote the password properly.
Am I missing something?
EDIT:
The problem with the continuous timeout password prompted was because the password didn't have \n at the end. I was expecting the lib to take care of it but it didn't.
Now that I am able to send the password to the remote device, I run into another issue. After I send the password via libssh2_channel_write(), subsequent libssh2_channel_read() fails with
LIBSSH2_ERROR_SOCKET_RECV
I am not sure why is this happening. Logic was to check if the libssh2_channel_write() was successful by doing a subsequent read() (which would give the command prompt on the remote device) and then issue the command to be executed on the remote device followed by a subsequent read to get the command output. Am I doing something wrong? This doesn't seem to be working. Here's the complete code snippet:
/*
* Sample showing how to use libssh2 to execute a command remotely.
*
* The sample code has fixed values for host name, user name, password
* and command to run.
*
* Run it like this:
*
* $ ./ssh2_exec 127.0.0.1 user password "uptime"
*
*/
#include "libssh2_config.h"
#include <libssh2.h>
#include <string.h>
#ifdef HAVE_WINSOCK2_H
#include <winsock2.h>
#endif
#ifdef HAVE_SYS_SOCKET_H
#include <sys/socket.h>
#endif
#ifdef HAVE_NETINET_IN_H
#include <netinet/in.h>
#endif
#ifdef HAVE_SYS_SELECT_H
#include <sys/select.h>
#endif
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#ifdef HAVE_ARPA_INET_H
#include <arpa/inet.h>
#endif
#include <sys/time.h>
#include <sys/types.h>
#include <stdlib.h>
#include <fcntl.h>
#include <errno.h>
#include <stdio.h>
#include <ctype.h>
static int waitsocket(int socket_fd, LIBSSH2_SESSION *session)
{
struct timeval timeout;
int rc;
fd_set fd;
fd_set *writefd = NULL;
fd_set *readfd = NULL;
int dir;
timeout.tv_sec = 10;
timeout.tv_usec = 0;
FD_ZERO(&fd);
FD_SET(socket_fd, &fd);
/* now make sure we wait in the correct direction */
dir = libssh2_session_block_directions(session);
if(dir & LIBSSH2_SESSION_BLOCK_INBOUND)
readfd = &fd;
if(dir & LIBSSH2_SESSION_BLOCK_OUTBOUND)
writefd = &fd;
rc = select(socket_fd + 1, readfd, writefd, NULL, &timeout);
return rc;
}
int main(int argc, char *argv[])
{
const char *hostname = "10.10.10.10";
const char *commandline = "show version";
const char *username = "user1";
const char *password = "password1";
unsigned long hostaddr;
int flag = 0;
int sock;
struct sockaddr_in sin;
const char *fingerprint;
LIBSSH2_SESSION *session;
LIBSSH2_CHANNEL *channel;
int rc;
int exitcode;
char *exitsignal=(char *)"none";
int bytecount = 0;
size_t len;
LIBSSH2_KNOWNHOSTS *nh;
int type;
if (argc > 1)
/* must be ip address only */
hostname = argv[1];
if (argc > 2) {
username = argv[2];
}
if (argc > 3) {
password = argv[3];
}
if (argc > 4) {
commandline = argv[4];
}
rc = libssh2_init (0);
if (rc != 0) {
fprintf (stderr, "libssh2 initialization failed (%d)\n", rc);
return 1;
}
hostaddr = inet_addr(hostname);
printf("host address is: %ld\n", hostaddr);
/* Ultra basic "connect to port 22 on localhost"
* Your code is responsible for creating the socket establishing the
* connection
*/
sock = socket(AF_INET, SOCK_STREAM, 0);
sin.sin_family = AF_INET;
sin.sin_port = htons(22);
sin.sin_addr.s_addr = hostaddr;
if (connect(sock, (struct sockaddr*)(&sin),
sizeof(struct sockaddr_in)) != 0) {
fprintf(stderr, "failed to connect!\n");
return -1;
}
/* Create a session instance */
session = libssh2_session_init();
if (!session)
return -1;
//libssh2_trace(session, LIBSSH2_TRACE_AUTH|LIBSSH2_TRACE_SOCKET);
/* tell libssh2 we want it all done non-blocking */
libssh2_session_set_blocking(session, 0);
/* ... start it up. This will trade welcome banners, exchange keys,
* and setup crypto, compression, and MAC layers
*/
while ((rc = libssh2_session_handshake(session, sock)) ==
LIBSSH2_ERROR_EAGAIN);
if (rc) {
fprintf(stderr, "Failure establishing SSH session: %d\n", rc);
return -1;
}
nh = libssh2_knownhost_init(session);
if(!nh) {
/* eeek, do cleanup here */
return 2;
}
/* read all hosts from here */
libssh2_knownhost_readfile(nh, "known_hosts",
LIBSSH2_KNOWNHOST_FILE_OPENSSH);
/* store all known hosts to here */
libssh2_knownhost_writefile(nh, "dumpfile",
LIBSSH2_KNOWNHOST_FILE_OPENSSH);
fingerprint = libssh2_session_hostkey(session, &len, &type);
if(fingerprint) {
struct libssh2_knownhost *host;
#if LIBSSH2_VERSION_NUM >= 0x010206
/* introduced in 1.2.6 */
int check = libssh2_knownhost_checkp(nh, hostname, 22,
fingerprint, len,
LIBSSH2_KNOWNHOST_TYPE_PLAIN|
LIBSSH2_KNOWNHOST_KEYENC_RAW,
&host);
#else
/* 1.2.5 or older */
int check = libssh2_knownhost_check(nh, hostname,
fingerprint, len,
LIBSSH2_KNOWNHOST_TYPE_PLAIN|
LIBSSH2_KNOWNHOST_KEYENC_RAW,
&host);
#endif
fprintf(stderr, "Host check: %d, key: %s\n", check,
(check <= LIBSSH2_KNOWNHOST_CHECK_MISMATCH)?
host->key:"<none>");
/*****
* At this point, we could verify that 'check' tells us the key is
* fine or bail out.
*****/
}
else {
/* eeek, do cleanup here */
return 3;
}
libssh2_knownhost_free(nh);
if ( strlen(password) != 0 ) {
/* We could authenticate via password */
while ((rc = libssh2_userauth_password(session, username, password)) ==
LIBSSH2_ERROR_EAGAIN);
if (rc) {
fprintf(stderr, "Authentication by password failed.\n");
goto shutdown;
}
}
else {
/* Or by public key */
while ((rc = libssh2_userauth_publickey_fromfile(session, username,
"/home/user/"
".ssh/id_rsa.pub",
"/home/user/"
".ssh/id_rsa",
password)) ==
LIBSSH2_ERROR_EAGAIN);
if (rc) {
fprintf(stderr, "\tAuthentication by public key failed\n");
goto shutdown;
}
}
#if 1
//libssh2_trace(session, ~0 );
#endif
/* Exec non-blocking on the remove host */
while( (channel = libssh2_channel_open_session(session)) == NULL &&
libssh2_session_last_error(session,NULL,NULL,0) ==
LIBSSH2_ERROR_EAGAIN )
{
waitsocket(sock, session);
}
if( channel == NULL )
{
fprintf(stderr,"Error\n");
exit( 1 );
}
while( (rc = libssh2_channel_exec(channel, commandline)) ==
LIBSSH2_ERROR_EAGAIN )
{
waitsocket(sock, session);
}
if( rc != 0 )
{
fprintf(stderr,"Error\n");
exit( 1 );
}
for( ;; )
{
/* loop until we block */
int rc;
do
{
char buffer[0x4000];
rc = libssh2_channel_read( channel, buffer, sizeof(buffer) );
if( rc > 0 )
{
int i;
char *enable = "check-password\n";
int ret;
bytecount += rc;
fprintf(stderr, "We read [%d] bytes:\n", bytecount);
fputc('[', stderr);
for( i=0; i < rc; ++i )
fputc( buffer[i], stderr);
fputc(']', stderr);
if ( strstr(buffer, "Password:") != NULL ){
fprintf(stderr, "Sending the password now\n");
while((ret = libssh2_channel_write(channel, enable, strlen(enable))) == LIBSSH2_ERROR_EAGAIN) {
printf("ERROR_EAGAIN - sending password again\n");
}
fprintf(stderr, "Wrote [%d] bytes: \n", ret);
flag = 1;
continue;
}
if (!flag){ // start
char *cmd = "show clock\n";
int ret;
fprintf(stderr, "THIS is Fetching show clock command now\n");
while((ret = libssh2_channel_write(channel, cmd, strlen(cmd))) == LIBSSH2_ERROR_EAGAIN) {
printf("ERROR_EAGAIN - sending show clock again\n");
}
flag = 1;
} // end
}
else {
if(rc != LIBSSH2_ERROR_EAGAIN)
fprintf(stderr, "libssh2_channel_read returned [%d]:\n ", rc);
}
}
while( rc > 0 );
/* this is due to blocking that would occur otherwise so we loop on
this condition */
if( rc == LIBSSH2_ERROR_EAGAIN )
{
int check;
check = waitsocket(sock, session);
}
else
break;
}
exitcode = 127;
while( (rc = libssh2_channel_close(channel)) == LIBSSH2_ERROR_EAGAIN )
waitsocket(sock, session);
if( rc == 0 )
{
exitcode = libssh2_channel_get_exit_status( channel );
libssh2_channel_get_exit_signal(channel, &exitsignal,
NULL, NULL, NULL, NULL, NULL);
}
if (exitsignal)
fprintf(stderr, "\nGot signal: %s\n", exitsignal);
else
fprintf(stderr, "\nEXIT: %d bytecount: %d\n", exitcode, bytecount);
libssh2_channel_free(channel);
channel = NULL;
shutdown:
libssh2_session_disconnect(session,
"Normal Shutdown, Thank you for playing");
libssh2_session_free(session);
#ifdef WIN32
closesocket(sock);
#else
close(sock);
#endif
fprintf(stderr, "all done\n");
libssh2_exit();
return 0;
}
Any thoughts?
#include <winsock2.h>
#include <stdio.h>
const int PORT = 6667;
const char *SERVER = "irc.freenode.org";
const char *CHAN = "#channela";
const char *NICK = "loveMilk";
const int MAX_BUFF_SIZE = 512;
int sock_conn(SOCKET *socketn, const char *HOST, int portn);
int sock_send(SOCKET *socketn, char* msg, ...);
int main(int argc, char *argv[])
{
WSADATA wsadata;
char buff[MAX_BUFF_SIZE];
char oBuff[MAX_BUFF_SIZE];
int buffRec;
if (WSAStartup(MAKEWORD(2,2), &wsadata) != 0)
return 0;
SOCKET sock;
if(sock_conn(&sock, SERVER, PORT) != 0)
{
WSACleanup();
return 0;
}
printf("connected.\n");
sock_send(&sock, "USER %s \"\" \"127.0.0.1\" :%s\r\n", NICK, NICK);
sock_send(&sock, "NICK %s\r\n", NICK);
Sleep(100);
sock_send(&sock, "JOIN %s\r\n", CHAN);
printf("Joined channel.\n");
while(1)
{
memset(buff, 0, MAX_BUFF_SIZE);
memset(oBuff, 0, MAX_BUFF_SIZE);
buffRec = recv(sock, buff, MAX_BUFF_SIZE, 0);
if((buffRec == 0) || (buffRec == SOCKET_ERROR)) break;
if(buff[0] != ':')
{
strcpy(oBuff, "PONG :");
printf("PONG");
sock_send(&sock, oBuff);
}
else
{
if(strstr(buff, "PRIVMSG"))
{
int i, num = 0;
for(i = 0; i < strlen(buff); ++i) if(buff[i] = ' ') ++num;
char** parts = malloc(sizeof(char*) * num);
char *p;
p = strtok(buff, " ");
int j = 0;
while(p != NULL)
{
parts[j] = p;
j++;
p = strtok(NULL, " ");
}
free(parts);
}
}
}
closesocket(sock);
return 1;
}
int sock_conn(SOCKET *socketn, const char *HOST, int portn)
{
WSADATA wsadata;
SOCKADDR_IN sockA;
LPHOSTENT hostE;
if(WSAStartup(MAKEWORD(2,2), &wsadata) == -1) return -1;
if(!(hostE = gethostbyname(HOST)))
{
WSACleanup();
return -1;
}
if ((*socketn = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == INVALID_SOCKET)
{
WSACleanup();
return -1;
}
sockA.sin_family = AF_INET;
sockA.sin_port = htons(portn);
sockA.sin_addr = *((LPIN_ADDR)*hostE->h_addr_list);
if(connect(*socketn, (LPSOCKADDR)&sockA, sizeof(struct sockaddr)) == SOCKET_ERROR)
{
WSACleanup();
return -1;
}
}
int sock_send(SOCKET *socketn, char* msg, ...)
{
char buff[MAX_BUFF_SIZE];
va_list va;
va_start(va, msg);
vsprintf(buff, msg, va);
va_end(va);
send(*socketn, buff, strlen(buff), 0);
return 1;
}
If I try to print buff after the if(strstr(buff, "PRIVMSG")) it crashes.
The while with the strtok won't work, if I try to reach parts[0] it crashes.
I tried to print parts[0] but shows nothing, tried to print during the while loop, shows nothing.
why?
You don't terminate your strings!
Edit the receiving part as this:
buffRec = recv(sock, buff, MAX_BUFF_SIZE, 0);
if((buffRec == 0) || (buffRec == SOCKET_ERROR)) break;
/* New line: Terminate buffer as a string */
buff[buffRec] = '\0';
As the other answer points out, a character array must end with '\0' to be considered a string. I think that C doesn't distinguish between the two, but you need the '\0' to signify the end of string. This could be why strstr(buff, "PRIVMSG")) isn't returning anything. It may default to null (thus not satisfying your if) because it doesn't think it has been passed a string.
'strtok(string, delimiter)' breaks an input string into tokens by using the delimiter. Here, you have passed it NULL as its string and " " as its delimiter. I am unfamiliar with many string functions (still learning C myself), but I think this is incorrect usage in your code.
parts[] does not seem to be defined in the code you've given. Its first use is where you try to store data in it for the inner while loop. Are there any other parts to the program that are not shown?