0

I am currently working on a server(basically a background service that allows the write in database to happen) in C which receives data streams in the form of a string from two different python clients, which in turn uses delimiters to seperate the tokens generated from the string and write them to the respective/different xml files. The code part might seem long, but it is a really simple program so please bear with me and try to help as I am a newbie when it comes to client-server architecture and would like to learn all these complexities. Thanks in advance.

My C Program:

#include<stdio.h>
#include<sys/socket.h>
#include<arpa/inet.h> //inet_addr
#include<unistd.h>
#include<string.h>
#include<stdlib.h>
#include<string.h>



int main(int argc , char *argv[])
{
    int socket_desc , new_socket , c, valread;
    struct sockaddr_in server, client ;
    char *message;
    char buffer[1024] = {0};
    char *hello = "Hello from server";
    int opt = 1;
    char *string;
    const char s[2] = ";";
    char *token;
    char *sid;
    char *name;
    char *host;
    char *port;
    char *proto;
    char *user;
    char *password;
    char *key;
    char *companyName;
    char *officeAddress;
    char *state;
    char *country;
    char *ladmin;
    char *phone;
    char *mobile;
    char *email;
    char *designation;
    char *rmanager;
    char *sip;
    char *polname;
    char *device;
    char *status;
    char *srczone;
    char *dstzone;
    char *srcaddr;
    char *dstaddr;
    char *srcuser;
    char *app;
    char *service;
    char *urlcategory;
    char *action;






 //Create socket
    socket_desc = socket(AF_INET , SOCK_STREAM , 0);
    if (socket_desc == 0)
    {
        printf("Could not create socket");
    }


    if (setsockopt(socket_desc, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT, &opt, sizeof(opt)))
    {
    perror("setsockopt");
    exit(EXIT_FAILURE);
    }


    //Prepare the sockaddr_in structure
    server.sin_family = AF_INET;
    server.sin_addr.s_addr = INADDR_ANY;
    server.sin_port = htons( 8888 );



    //Bind
    if( bind(socket_desc,(struct sockaddr *)&server , sizeof(server)) < 0)
    {
   puts("bind failed");
    }


     puts("bind done");




    //Listen
    listen(socket_desc , 3);
  while(1){
    //Accept and incoming connection
  puts("Waiting for incoming connections...");
    c = sizeof(struct sockaddr_in);
    new_socket = accept(socket_desc, (struct sockaddr *)&client, (socklen_t*)&c);
    if (new_socket<0)
    {
        perror("accept failed");
    }

    puts("Connection accepted\n");




    valread = read(new_socket, buffer, 1024);
    printf("%s\n", buffer);
    string = buffer;

//Macro that I am using to distinguish between clients and the work to be done
    token = strtok(string,s);

//If server is passed as the first token, following code to be executed
    printf("%s", token);
    if( token == "server" ){
    sid = strtok(NULL, s);
    printf("\nSERVER-ID: %s\n", sid);
    name = strtok(NULL, s);
    printf("\nName: %s\n", name);
    host = strtok(NULL,s);
    printf("\nHost: %s\n", host);
    port = strtok(NULL,s);
    printf("\nPort: %s\n", port);
    proto = strtok(NULL,s);
    printf("\nProto: %s\n", proto);
    user = strtok(NULL,s);
    printf("\nUser: %s\n", user);
    password = strtok(NULL, s);
    printf("\nPassword: %s\n", password);
    key = strtok(NULL,s);
    printf("\nKey: %s\n", key);
    companyName = strtok(NULL,s);
    printf("\nCompanyName: %s\n", companyName);
    officeAddress = strtok(NULL,s);
    printf("\nOfficeAddress: %s\n", officeAddress);
    state = strtok(NULL,s);
    printf("\nState: %s\n", state);
    country = strtok(NULL,s);
    printf("\nCountry: %s\n", country);
    email = strtok(NULL,s);
    printf("/nEmail: %s\n", email);
    ladmin = strtok(NULL,s);
    printf("\nLAdmin: %s\n", ladmin);
    phone = strtok(NULL,s);
    printf("\nPhone: %s\n", phone);
    mobile = strtok(NULL,s);
    printf("\nMobile: %s\n", mobile);
    designation = strtok(NULL, s);
    printf("\nDesignation: %s\n", designation);
    rmanager = strtok(NULL, s);
    printf("\nReportingManager: %s\n", rmanager);

    FILE *xml_file;
    xml_file = fopen("/var/www/db/db_server_list.xml", "a+");
    fseek(xml_file, -8, SEEK_END);

    ftruncate(fileno(xml_file),ftello(xml_file));





    fprintf(xml_file, "\n<server id='%s'>\n", sid);
    fprintf(xml_file, "   <name>%s</name>\n", name);
    fprintf(xml_file, "   <host>%s</host>\n", host);
    fprintf(xml_file, "   <port>%s</port>\n", port);
    fprintf(xml_file, "   <proto>%s</proto>\n", proto);
    fprintf(xml_file, "   <user>%s</user>\n", user);
    fprintf(xml_file, "   <password>%s</password>\n", password);
    fprintf(xml_file, "   <key>%s</key>\n", key);
    fprintf(xml_file, "   <companyName>%s</companyName>\n", companyName);
    fprintf(xml_file, "   <address>\n");
    fprintf(xml_file, "     <officeAddr>%s</officeAddr>\n", officeAddress);
    fprintf(xml_file, "     <state>%s</state>\n", state);
    fprintf(xml_file, "     <country>%s</country>\n", country);
    fprintf(xml_file, "   </address>\n");
    fprintf(xml_file, "   <contacts>\n");
    fprintf(xml_file, "     <ladmin>%s</ladmin>\n", ladmin);
    fprintf(xml_file, "     <phone>%s</phone>\n", phone);
    fprintf(xml_file, "     <mobile>%s</mobile>\n", mobile);
    fprintf(xml_file, "     <email>%s</email>\n", email);
    fprintf(xml_file, "     <designation>%s</designation>\n", designation);
    fprintf(xml_file, "     <rManager>%s</rManager>\n", rmanager);
    fprintf(xml_file, "   </contacts>\n");
    fprintf(xml_file, " </server>\n", key);
    fprintf(xml_file, "</data>");

    fclose(xml_file);
 send(new_socket, hello, 17, 0);
    printf("\nSocket: Sent data to the client!\n");
}
else if (token == "policy"){
    sip = strtok(NULL, s);
    printf("\nserverip: %s\n", sip);
    polname = strtok(NULL, s);
    printf("\nPolicy Name: %s\n", polname);
    device = strtok(NULL,s);
    printf("\nDevice Name: %s\n", device);
    status = strtok(NULL,s);
    printf("\nStatus: %s\n", status);
    srczone = strtok(NULL,s);
    printf("\nSrcZone: %s\n", srczone);
    dstzone = strtok(NULL,s);
    printf("\nDstZone: %s\n", dstzone);
    srcaddr = strtok(NULL, s);
    printf("\nSrcAddr: %s\n", srcAddr);
    dstaddr = strtok(NULL,s);
    printf("\nDstAddr: %s\n", dstAddr);
    srcuser = strtok(NULL,s);
    printf("\nSrcUser: %s\n", srcuser);
    app = strtok(NULL,s);
    printf("\nApplication: %s\n", app);
    service = strtok(NULL,s);
    printf("\nService: %s\n", service);
    urlcategory = strtok(NULL,s);
    printf("\nUrlCategory: %s\n", urlcategory);
    action = strtok(NULL,s);
    printf("/nAction: %s\n", action);

    FILE *xml_file;
    xml_file = fopen("/var/www/db/db_policy.xml", "a+");
    fseek(xml_file, -14, SEEK_END);

    ftruncate(fileno(xml_file),ftello(xml_file));





    fprintf(xml_file, "\n<policyDecryption>\n",);
    fprintf(xml_file, "   <policyName>%s</policyName>\n", polname);
    fprintf(xml_file, "   <deviceName>%s</deviceName>\n", device);
    fprintf(xml_file, "   <status>%s</status>\n", status);
    fprintf(xml_file, "   <srcZone>%s</srcZone>\n", srczone);
    fprintf(xml_file, "   <dstZone>%s</dstZone>\n", dstzone);
    fprintf(xml_file, "   <srcAddr>%s</srcAddr>\n", srcaddr);
    fprintf(xml_file, "   <dstAddr>%s</dstAddr>\n", dstaddr);
    fprintf(xml_file, "   <srcUser>%s</srcUser>\n", srcuser);
    fprintf(xml_file, "   <application>%s</application>\n", app);
    fprintf(xml_file, "   <service>%s</service>\n", service);
    fprintf(xml_file, "   <urlCategory>%s</urlCategory>\n", urlcategory);
    fprintf(xml_file, "   <action>%s</action>\n", action);
    fprintf(xml_file, " </policyDecryption>\n");
    fprintf(xml_file, "</policyList>");

    fclose(xml_file);
  send(new_socket, hello, 17, 0);
    printf("\nSocket: Sent data to the client!\n");


}
}

    return 0;
}

When I tried sending the data to this server without using the macro, it prints the macro as well and now that I have added the second macro and the followed by code as well, the client gets stuck and no printing/writing into the database takes place and I have to end the execution using Ctrl+C in order to stop.

Is this a right approach to solve my problem? Am I doing anything wrong? I know this is not the best way to do this work, so any and all suggestions are welcome.

The clients are python based CGI scripts which take dynamic data from a UI page and send that data as a string. I am attaching "server" and "policy" as two different macros that are supposed to be read and the following code to be executed accordingly.

Devanshu Misra
  • 773
  • 1
  • 9
  • 28
  • 2
    I think you need to take a few steps back and [get a couple of good beginners books](http://stackoverflow.com/questions/562303/the-definitive-c-book-guide-and-list). An expression like `token == "server"` will not do what you think it does. – Some programmer dude Nov 22 '17 at 09:48
  • 1
    Comparing strings: https://stackoverflow.com/questions/8004237/how-do-i-properly-compare-strings – Klas Lindbäck Nov 22 '17 at 09:52
  • 2
    Actually you are not far off. Most is correct C, except for comparing strings, which requires the use of `strcmp`, for example `if( strcmp(token, "server")==0 )`. – Paul Ogilvie Nov 22 '17 at 10:04
  • 1
    That was great help guys, and I am thankful @Someprogrammerdude for actually telling me to go through the books for getting my basics strong. Klas Lindback and Paul Ogilvie thank you for poiniting my mistake to me. I will get back to you guys once I implement these suggestions. – Devanshu Misra Nov 22 '17 at 10:34
  • `string = buffer; token = strtok(string,s);` buffer is not NUL-terminated. `valread=read()` can be anything from -1 to 1024 . – wildplasser Nov 22 '17 at 11:58
  • @PaulOgilvie thanks for that help man. Now i can use my C service to distinguish between what process to go through and which part of the code to execute. It was really because I did not use the right string compare method – Devanshu Misra Nov 23 '17 at 06:25
  • @wildplasser You made a valid point sir, but the problem that I had, had nothing to do with my buffer. Moreover `valread=read()` is used to read the buffer only, which is later converted to `utf-8` coding or ASCII characters, which can further be broken down into tokens using the delimiters that I have used further. And it is not NULL terminated, once the front part of the string/buffer is read, it discards the value I guess as it is able to read the other part of the string easily as well. I can share my output if you want :) – Devanshu Misra Nov 23 '17 at 06:28
  • 1
    @DevanshuMisra :just wait till Nagle kicks in.Or your IP-frames get fragmented. – wildplasser Nov 23 '17 at 09:17
  • @wildplasser thank you for giving me a heads up on this and will surely read about this and implement your suggestions accordingly. Can you please give me some reference material about Nagle and IP-frames getting fragmented, that I can go through so that this problem(which you stated) gets tackled before it arises? – Devanshu Misra Nov 23 '17 at 10:45
  • https://stackoverflow.com/q/6263829/905902 [for buffering streams] – wildplasser Nov 23 '17 at 19:10

1 Answers1

0

C++ ssl server with multiple connections https://github.com/breakermind/cppSockets/tree/master/SslServerExample

Working example with C++ fork() function or with threads.

fork() - server create new prossess for each new connection

thread() - server create new thread for each new connection

You need change only part in this function/method

void ServerLoop(SSL *ssl, string ipAddress){ }

You can test connections from openssl client

openssl s_client -connect hostname:999

If connect to smtp server then

openssl s_client -connect hostname:25 -starttls smtp
bocz
  • 11
  • 2