Newsgroup: it.comp.lang.c
Titolo: Help codice!

Salve ragazzi, sto scrivendo un mini server web che supporti il protocollo
HTTP//1.0. Mi accadono fatti strani e differenti, a seconda se lo compilo
su una piattaforma o su un altra (Windows, Linux-x86, LinuxPPc, MacOSX).
Soprattutto non capisco perchè l'esecuzione si blocchi in alcuni punti del
codice. Purtroppo non sono bravo con gdb. Chiedo a qualcuno un
suggerimento ed un aiuto.
Grazie di cuore,
Nat
/// LISTATO web_server.h
/*
 *  web_server.h
 *  WebClientServerHTTP1_0
 *
 *  Created by Letizia Natale on 6/9/05.
 *  Copyright 2005 __MyCompanyName__. All rights reserved.
 *
 */
#include <errno.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <netinet/in.h>   
#include <ctype.h>
#include <string.h>
#define MAXBUF 1024
#define SERVERPORT 5050
#define SERVERNAME "localhost"
/// LISTATO web_server.c
/*
 *  web_server.c
 *  WebClientServerHTTP1_0
 *
 *  Created by Letizia Natale on 6/9/05.
 *  Copyright 2005 __MyCompanyName__. All rights reserved.
 *
 */
#include "web_server.h"
char buffer[MAXBUF];
void doserv(int sock);
void concat(char * str1, char * str2);
void substring(char * str, int index);
int ends_with(char* str, char * substr);
static void send_header(int sock, int status_code, FILE* body);
static void send_body(int sock, FILE* file);
int main(int argc, char * argv[])
{
   int server_socket, connect_socket;
   int client_addr_len, retcode;
   struct sockaddr_in client_addr,     // NB: type cast later
                      server_addr;
   char * addrp;
   // apertura del socket del server
   if ( (server_socket = socket(AF_INET,SOCK_STREAM,0)) == -1)
   {
      perror("aprendo il socket del server"); 
      exit(-1);
   }
 
 
   // preparazione dell'indirizzo per il socket
   bzero(&server_addr,sizeof(server_addr)); // some operatings systems
requires previously zero filling
 
   server_addr.sin_family = AF_INET;
   server_addr.sin_port = htons(SERVERPORT);
   addrp = gethostbyname(SERVERNAME)->h_addr;
   memcpy(&server_addr.sin_addr, addrp, sizeof(addrp));
   ////
 
   // DEBUG
   /*
   printf("MAXBUF %d\n",MAXBUF);
   printf("SERVERPORT %d\n",SERVERPORT);
   printf("SERVERNAME %s\n",SERVERNAME);
   printf("Trying to bind to port %d\n", ntohs(server_addr.sin_port));
   printf("Trying to bind to address %s\n", inet_ntoa(server_addr.sin_addr));
   */
   ///
 
   // pubblicazione del socket
   retcode = bind(server_socket, (const struct sockaddr *) &server_addr,
(socklen_t) sizeof(server_addr) ); // socklen_t ˆ® un "alias" per int
 
   if(retcode == -1)
   {
      perror("error binding socket"); 
      exit(-1);
   }
 
   retcode = listen(server_socket, 1);
   if(retcode == -1)
   {
      perror("error listening"); 
      exit(-1);
   }
   printf("Server ready (CTRL-C quits)\n");
   // ciclo che accetta le connessioni
   client_addr_len = sizeof(client_addr);
   while ( 1 ) // infinite loop
   {
      if ((connect_socket = accept(server_socket, (struct sockaddr *) &
client_addr, (socklen_t *)&client_addr_len)) == -1) 
      {
         perror("accepting");
         close(server_socket);
         exit(-1);
      }
      if (fork() == 0) 
      {  //figlio: esegue servizio
         printf("\nClient@%s connects on socket %d; sends:\n",
inet_ntoa(client_addr.sin_addr),connect_socket);
         //printf("hi\n");
         // cycle: process data from accepted connection
         while ((retcode = read(connect_socket, buffer, MAXBUF))> 0) 
         {
            buffer[retcode] = '\0';    // buffer must be a string
 
            //write(fileno(stdout), buffer, retcode);
            doserv(connect_socket);
         }
         if (retcode == 0 || errno == EPIPE) // read returned 0 or -1
            printf("Client closed connection on socket %d\n", connect_socket);
         else // retcode == -1 && (errno != EPIPE)
            perror(">>reading from connection");
         close(connect_socket);
         exit(0);
      }        // figlio: esce, servizio eseguito
      else     // padre: riprende ad ascoltare dopo aver chiuso la socket
         close(connect_socket);  // se non lo fa, le prossime mantengono il n.
   }  // end while (never gets here)
}
const char * HTML_TYPE="text/html";
char * type="text/html";
////
void doserv(int sock)
{
   int i,j;
   unsigned delay;
 
   char * method=NULL, *file_name=NULL, *http_version=NULL, *bad_word=NULL;
   method=(char *)malloc(strlen("HEAD")+1);
   file_name=(char *)malloc(256);
   http_version=(char *)malloc(strlen("HTTP/1.0")+1);
   bad_word=(char *)malloc(256);
 
   int num_of_bytes=0;
   FILE* file400=NULL, *file404=NULL, *file500=NULL, *file501=NULL, *file=NULL;
   file400=fopen("400.html","r");
   file404=fopen("404.html","r");
   file500=fopen("500.html","r"); 
   file501=fopen("501.html","r"); 
 
 
   // scansione dei token
   printf("REQUEST LINE is: %s,\n",buffer); 
 
   for(i=0; buffer[i]!=' ' && buffer[i]!='\0'; i++);
 
   printf("i is: %d\n",i);
   printf("method is: %s\n",method);
   strncpy(method,buffer,i);
 
   printf("METHOD: %s\n",method);
   printf("METHOD length: %d\n",strlen(method));
 
   for(j=i=i+1; buffer[j]!=' ' && buffer[j]!='\0'; j++);
 
   strncpy(file_name,buffer+i,j-i);
 
   printf("FILE_NAME: %s\n",file_name);
   i=j;
   for(j=i=i+1; buffer[j]!=' ' && buffer[j]!='\0'; j++);
 
   strncpy(http_version,buffer+i,j-i);
   printf("HTTP_VERSION: %s\n",http_version);
 
   //printf("ROW length is: %d\n",strlen(buffer));
   //printf("j is: %d\n",j);
   //printf("the character on pos j is (between brackets ''):
'%c'\n",buffer[j]);
   printf("dunque");
   /*
   if(buffer[j]==' ')
   {
      printf("case special");
   }
   if(buffer[j]!='\0')
   {
      printf("bad_word found");
      bad_word="BAD_WORD";
   }
   else
   {
      printf("correct request-line");
   // bad_word="";
   }
   */
   //printf("BAD_WORD: %s\n",bad_word);
 
   if(strcmp(method,"GET")==0)
   {
      printf("the method is get!");
      if(file_name=="HTTP/1.0"||(http_version!="HTTP/1.0" &&
http_version!="HTTP/1.1")||bad_word!="")
      {
 
         *type=*HTML_TYPE;
         send_header(sock,400,file400);
         send_body(sock,file400);
      }
      else
      {
         if(file_name=="/")
            file_name="index.html";
         if(&file_name[0]=="/")
         {
            substring(file_name,1);
            if ((file=fopen(file_name,"rt"))>=0)
            { 
               int i;
               i=0;
               for (; i < strlen(file_name) ; i++) 
                  file_name[i] = tolower(file_name[i]);
 
               if(ends_with(file_name,".htm")||ends_with(file_name,".html"))
                  *type=*HTML_TYPE;
               else if(ends_with(file_name,".txt"))
                  type="text/plain";
               else
if(ends_with(file_name,".jpg")||ends_with(file_name,".jpeg"))
                  type="image/jpeg";
               else if(ends_with(file_name,".gif"))
                  type="image/gif";
               else
                  type="application/octet-stream";
 
               send_header(sock,200,file);
               send_body(sock,file);
            }
            else
            {
               *type=*HTML_TYPE;
               send_header(sock,404,file404);
               send_body(sock,file404);
            }
         }
      }
   }
   else
      printf("WORK IN PROGRESS");   
 
    // simula un ritardo
    if ( (delay = (unsigned) (buffer[0]-'A')) < 30 )  
   {
      printf("\nServer delay %u\n",delay); 
      sleep(delay);
   }
 
   // risponde
   if (write(sock, buffer, strlen(buffer)+1) < 0)
      perror("replying to client");
}
void concat(char * str1, char * str2) {
    int i, j;
    i = 0;
    while (str1[i] != '\0')
        i++;
    j = 0;
    while (str2[j] != '\0') {
         str1[i] = str2[j];
         i++;
         j++;
    }
    str1[i] = '\0';
}
void substring(char * str, int index)
{
   int i;
   i=0;
   while(str[i]!='\0')
   {
      str[i]=str[index];
      i++;
      index++;
   }
   str[i]='\0';
}
int ends_with(char* str, char * substr)
{
   int i;
   int len=strlen(substr);
   char * tmp;
   for(i=strlen(str)-len; i<strlen(str); i++)
      concat(tmp,&str[i]);
   return (tmp==substr);
}
static void send_header(int sock, int status_code, FILE* body) 
{
   switch(status_code)
   {
      case 200:
         if (write(sock, "HTTP/1.0 200 OK\r\n", strlen("HTTP/1.0 200
OK\r\n")+1) < 0)
            perror("replying to client");
      break;
 
      //case 304:
      // if (write(sock, "HTTP/1.0 304 Not Modified\r\n", strlen("HTTP/1.0
304 Not Modified\r\n")+1) < 0)
      //    perror("replying to client");
      //break;
 
      case 400:
         if (write(sock, "HTTP/1.0 400 Bad Request\r\n", strlen("HTTP/1.0
400 Bad Request\r\n")+1) < 0)
            perror("replying to client");
      break;
 
      case 404:
         if (write(sock, "HTTP/1.0 404 Not Found\r\n", strlen("HTTP/1.0
404 Not Found\r\n")+1) < 0)
            perror("replying to client");
      break;
 
      case 501:
         if (write(sock, "HTTP/1.0 501 Not Implemented\r\n",
strlen("HTTP/1.0 501 Not Implemented\r\n")+1) < 0)
            perror("replying to client");
      break;
 
      default:
         if (write(sock, "HTTP/1.0 500 Internal Server Error\r\n",
strlen("HTTP/1.0 500 Internal Server Error\r\n")+1) < 0)
            perror("replying to client");
      }
 
      //output.writeBytes("Date: "+date+"\r\n");
      //char * s="Server: "+server+"\r\n");
 
 
      //if(statusCode!=304)
      char * cont_len="Content-Length: ";
      concat(cont_len,(char*)sizeof(body));
      concat(cont_len,"\r\n");
 
      if (write(sock, &cont_len, strlen(cont_len)+1) < 0)
            perror("replying to client");
      //if(statusCode!=304)
         //output.writeBytes("Content-Type: "+type+"\r\n");
      char * cont_type="Content-Type: ";
      concat(cont_type,type);
      concat(cont_type,"\r\n");
 
      if (write(sock, &cont_type, strlen(cont_type)+1) < 0)
            perror("replying to client");
 
      /*if(statusCode==200)
      char * cont_type="Content-Type: ";
      concat(cont_type,type);
      concat(cont_type,"\r\n");
 
      if (write(sock, &cont_type, strlen(cont_type)+1) < 0)
            perror("replying to client");
         output.writeBytes("Last-Modified: "+lastModified+"\r\n");*/
 
      //output.writeBytes("\r\n");
      if (write(sock, "\r\n", strlen("\r\n")+1) < 0)
            perror("replying to client");
}
static void send_body(int sock, FILE* file) 
{
   int *tmp=0;
   int ret_code;
 
   do
   {
      if((ret_code=read((int)file,tmp,MAXBUF))<0)
         break;
      write(sock,tmp,sizeof(tmp));
   }
   while(1);
}

 Purtroppo non sono bravo con gdb.
bravO? Nel senso che non sei la Letizia autrice del codice? Meglio
cosi`... butta quel codice.
Gli errori vanno dalla gestione delle stringhe all'invio di roba errata
sul socket (in particolare mandi un sacco di '\0'...); ci vorrebbe
almeno un'ora per commentarti tutti gli errori.
Ricomincia da zero, creando prima un semplice listener, poi aggiungi il
parser e poi gradualmente aggiungi le feature previste dall'HTTP.
Luca
-- 
Home: 
http://kronoz.cjb.net
Collect some stars to shine for you
And start today 'cause there's only a few
A sign of times my friend

 suggerimento ed un aiuto.
Il mio suggerimento è di correggere il programma.
Vedrai che funzionerà.  Coraggio!

, Andrea Laforgia


 Grazie per il tuo intervento privo di utilità.
Speravo che tu ne carpissi il sottile significato, ma così non è stato.

 Grazie per il tuo intervento privo di utilità.
La risposta di Andrea per esteso sarebbe una cosa del tipo:
"Non puoi postare nel ng 400 righe di codice - di pessima qualita` -
dicendo semplicemente 'non va' e sperando che qualcuno di faccia i
compiti. Se hai delle domande specifiche saremo lieti di
aiutarti"
Luca
-- 
Home: 
http://kronoz.cjb.net
"La donna ideale deve soddisfare l'anima, lo spirito, i sensi.
 Non trovando riuniti i tre requisiti nella stessa persona, è
 consentito il frazionamento." -- Alessandro Morandotti


Per carita` di Dio, quando ho iniziato a leggere speravo di essere
d'aiuto, ora capisco che l'unica cosa da fare e` che tu legga un BUON
manuale di C. Dato il tuo livello, rimango scandalizzato dal tentativo
di programma nettamente al di sopra delle tue possibilita`.
Ti invito ad adottare un approccio diverso, oppure a darti all'ippica.
Saluti,
Marco
-- 
To email me, remove the no_ and _spam from my address.