libuv error - uninitialized stream - libuv

I am trying to use libuv to send some data. The client connects to the server, the server accepts the connection, then the client attempts to write using uv_write (the printf is output so I know it's getting this far). The result is
uv_write2: Assertion `(stream->type == UV_TCP || stream->type == UV_NAMED_PIPE || stream->type == UV_TTY) && "uv_write (unix) does not yet support other types of streams"' failed.
Which makes me think the stream must not be initialized. Code is below, what am I doing wrong?
void OnConnectToServer(uv_connect_t *client, int status)
{
if (status < 0)
{
return;
}
printf( "Client attempt write\n" );
write_req_t *req = (write_req_t*) malloc(sizeof(write_req_t));
req->buf = uv_buf_init( (char*) malloc(1), 1 );
(req->buf.base)[0] = '0';
uv_write((uv_write_t*) req, client->handle, &req->buf, 1, OnWrite);
}
void SendData( uv_async_t*sd )
{
uv_tcp_t client;
uv_tcp_init(loop, &client);
uv_connect_t* connect = (uv_connect_t*)malloc(sizeof(uv_connect_t));
struct sockaddr_in dest;
uv_ip4_addr("192.168.20.3", PORT, &dest);
uv_tcp_connect(connect, &client, (const struct sockaddr*)&dest, OnConnectToServer);
}

uv_write_t is the right struct, but you can't use req->buf which is a private field. You must declare a new variable like so:
uv_write_t *req = (uv_write_t*) malloc(sizeof(uv_write_t));
uv_buf_t buf = uv_buf_init( (char*) malloc(1), 1 );
buf.base[0] = '0';
uv_write(req, client->handle, &buf, 1, OnWrite);

Related

C UDP Client-Server stuck comunication

for one of my university courses I must realize a simple chat program in C that uses UDP Client-Server, this is the description that the teacher sent us:
You should develop a private chat environment to exchange
text messages between hosts. Message encryption is optional but not required.
The project should be composed by 2 main modules:
Server: receives and stores each message in a sort of chat database.
A very naive database would consist in a User struct,
that contains everything (login credentials, chats, ...).
Each Chat structure contains the actual messages.
Client: provides a very simple interface to select a
receiver for our message and then write the content of the message.
Login is required. If a receiver is not subscribed returns an error.
The project should be tested with at least 3 users :)
I managed to implement the authentication phase but then when trying to implement the message exchange phase I got stuck. When I try to send the linked_list of online users from the Server to the Client the execution freezes and not only that but it gives somewhat of random behavior, sometimes gets stuck on the first try sometimes on the second and so on. I also noticed that when I introduced a separated thread in the Client to handle the inbox of messages the situation got worst getting stuck more often then before. I will add the code of the functions responsible of sending and receiving the online users and also the link to my git repo where if you want you can find the complete code.
This is the code in the Server:
void Send_list(ListHead* head, int sockfd,struct sockaddr_in cliaddr, int size){
int written_bytes;
int len = sizeof(cliaddr);
char username[50];
if(head->size == 1){
return;
}
ListItem* aux = head->first;
for(int i=0;i<size;i++){
memset(username,0,sizeof(username));
UserListItem* uitem = (UserListItem*) aux;
strcpy(username,uitem->user.username);
do{
written_bytes = 0;
written_bytes = sendto(sockfd,(const char *)username,strlen(username),0,(const struct sockaddr*)&cliaddr,len);
}while(written_bytes != strlen(username));
printf("\nusername mandato: %s",username);
printf("\n");
if(aux->next){
aux = aux->next;
}
}
}
And this is the code in the Client:
int recv_list(int sockfd,struct sockaddr_in servaddr, ListHead* head,int size, char username[50]){
char onuser[50];
int len = sizeof(servaddr);
int read_bytes;
int idx = 1;
if(size == 1){
return 1;
}
for(int i=0;i<size;i++){
read_bytes = recvfrom(sockfd,(char *)onuser,sizeof(onuser),0,(struct sockaddr*)&servaddr,&len );
onuser[read_bytes] = '\0';
if(List_find_by_username(head,onuser) == 0 || strcmp(onuser,username)){
UserListItem* uitem = malloc(sizeof(UserListItem));
memset(uitem,0,sizeof(UserListItem));
UList_init(uitem,onuser);
uitem->idx = idx++;
ListItem* result = List_insert(head,head->last,(ListItem*)uitem);
assert(result);
}
memset(onuser,0,sizeof(onuser));
}
UserList_print(head);
return 0;
}
And this is the link to my git repo: https://gitlab.com/antonio_ciprani/so-progetto-20_21
I work in an Ubuntu based system.
I really hope that somebody can help me because this is driving me crazy :(
I also noticed that when I introduced a separated thread in the Client to handle the inbox of messages the situation got worst getting stuck more often then before.
Indeed the use of threads in your program does more harm than good. Especially that in the main loop you pthread_create a new reciving thread, which competes with the main thread for the incoming messages, disrupts the course of recv_list. Better don't use threads for your project - you'll avoid a lot of problems.
Let's first write two helper functions:
void store(thread_args_t *targs, Message *msg)
{ // code taken from your function "reciving"
if (!strcmp(targs->user->username, msg->reciver))
{
Inbox *mitem = malloc(sizeof (Inbox));
strcpy(mitem->msg.sender, msg->sender);
strcpy(mitem->msg.reciver, msg->reciver);
strcpy(mitem->msg.data, msg->data);
ListItem *result =
List_insert(targs->inbox, targs->inbox->last, (ListItem *)mitem);
assert(result);
}
}
char *input(thread_args_t *targs)
{ // wait for user input and store incoming messages
fflush(stdout);
fd_set fds, fdr;
FD_ZERO(&fds);
FD_SET(0, &fds); // add STDIN to the fd set
FD_SET(targs->sockfd, &fds); // add socket to the fd set
for (; ; )
{
if (fdr = fds, select(targs->sockfd+1, &fdr, NULL, NULL, NULL) < 0)
perror("select"), exit(1);
if (FD_ISSET(0, &fdr))
{ // this is the user's input
static char data[256];
if (!fgets(data, sizeof data, stdin)) return NULL; // no more user input
data[strlen(data)-1] = '\0';
return data;
}
// if no user input, then there's a message
Message msg;
socklen_t len = sizeof targs->servaddr;
if (recvfrom(targs->sockfd, &msg, sizeof msg, 0,
(struct sockaddr *)targs->servaddr, &len) < 0)
perror("recvfrom"), exit(1);
store(targs, &msg);
}
}
Now you can replace the main loop body in main with this:
int ret, op;
printf("\nPlease choose an option: ");
printf("\n1.Send a message!");
printf("\n2.Incoming messages!");
printf("\n3.Logout!");
printf("\nYour choice:\t");
char *str = input(&targs);
sscanf(str, "%d", &ret);
printf("\nqua bro?\n");
if (ret == 1)
{
printf("\nqua loz?\n");
int res, read_bytes, size, id;
op = 3;
socklen_t len = sizeof servaddr;
sendto(sockfd, &op, sizeof op, MSG_CONFIRM,
(struct sockaddr *)&servaddr, len);
printf("\nqua shiiis?\n");
// We cannot preclude that a message arrives here,
// therefore we must handle that case.
Message msg;
while ((read_bytes = recvfrom(sockfd, &msg, sizeof msg, 0,
(struct sockaddr *)&servaddr,
&len)) == sizeof msg)
store(&targs, &msg);
if (read_bytes == -1) perror("recvfrom"), exit(1);
size = *(int *)&msg;
printf("\nqua ci siamo?\n");
res = recv_list(sockfd, servaddr, &on_list, size, user.username);
printf("\nqua?\n");
if (res == 0)
{
printf("\nChoose whom you want to send a message to");
printf("\nYour choice:\t");
str = input(&targs);
sscanf(str, "%d", &id);
printf("\nWrite the message you want to send:\n");
str = input(&targs);
Init_msg(&msg, str, id, &on_list, user.username);
int written_bytes = sendto(sockfd, &msg, sizeof msg, MSG_CONFIRM,
(struct sockaddr *)&servaddr, len);
if (written_bytes == -1) perror("sendto"), exit(1);
// With your present server, a message cannot arrive here, but you
// possibly will want to change that, so let's handle it already.
while ((read_bytes = recvfrom(sockfd, &msg, sizeof msg, 0,
(struct sockaddr *)&servaddr,
&len)) == sizeof msg)
store(&targs, &msg);
if (read_bytes == -1) perror("recvfrom"), exit(1);
int sent = *(int *)&msg;
if (sent == 0) printf("\nMessage sent!");
else
if (sent == 1) printf("\nUser is offline :(");
}
else
if (res == 1) printf("\nNo online user :(");
}
else
if (ret == 2) Print_msg(&inbox);
The next thing you possibly want to improve is modifying the server function Forward_message so that it allows for incoming commands from another client while waiting for a message.

Repeated SSL_connect in C causes SIGSEGV

I have the following code, and I am getting SIGSEGV on the line:
if ( SSL_connect(ssl) == FAIL )
The fault Im getting is:
Program received signal SIGSEGV, Segmentation fault.
0x00007ffffe5a41e0 in __GI___libc_malloc (bytes=104) at malloc.c:2926
2926 malloc.c: No such file or directory.
The program basically is designed to take loads of data and push it into firebase.
The first one element, is to check if we are registered, the next bit is to actually do the registration.
Cutting the program back to basics, we have the following opening gambit:
int main(int argc, char *argv[]) {
int iRegistered = checkRegistered();
int result = registerCar();
}
If we swap those two lines, so we register before we check the registration, then we don't get a SIGSEGV.
Here's the checkRegistration function:
int checkRegistered() {
int firebaseRegistered = 0;
char *carId;
carId = (char *) malloc(256);
strcpy(carId, "aabbccddeeffgg" );
char *payload;
payload = (char *) malloc(1024);
sprintf(payload, "{ \"carid\": \"%s\" }", carId);
char *response;
response = (char *) malloc(1024);
int result = firebase("isCarRegistered", payload, &response);
if (result == 0) {
// Process JSON Response
cJSON *json = cJSON_Parse(response);
if (json == NULL) {
//
} else {
cJSON *json_registered = NULL;
json_registered = cJSON_GetObjectItemCaseSensitive(json, "registered");
firebaseRegistered = json_registered->valueint;
}
}
free(response);
free(payload);
free(carId);
return firebaseRegistered;
}
And the registerCar function.
They're basically mostly the same format - construct a message, send it to firebase, process the JSON response. We use cJSON to decompile the data returned from Firebase, though we could potentially use it to also compile. But one thing at a time.
You'll see a number of free() statements - I've been trying to work out how best to complete this - ie, generate a char* locally, pass by reference ** to a function, let the function perform the malloc/realloc based on the sizes it can calculate and then we can free it from the calling code once we have dealth with the data. Though I also get a SIGSEGV from that as well.
int registerCar() {
int iResponse = 0;
char *carId;
carId = (char *) malloc(256);
char *authCode;
authCode = (char *) malloc(12);
char *payload;
payload = (char *) malloc(1024);
sprintf(payload, "{ }");
char *response;
response = (char *) malloc(1024);
int result = firebase("registerCar", payload, &response);
if (result == 0) {
// Process JSON Response
cJSON *json = cJSON_Parse(response);
if (json == NULL) {
//
} else {
cJSON *json_auth = NULL;
cJSON *json_car = NULL;
json_auth = cJSON_GetObjectItemCaseSensitive(json, "authcode");
json_car = cJSON_GetObjectItemCaseSensitive(json, "carid");
iResponse = 1;
}
}
free(response);
free(payload);
return iResponse;
}
Here's the firebase routine, it takes a function, a payload and generates a response. Interestingly here, char firebaseLocal and charfirebaseMessage is not always null before the initial malloc.
int firebase(char *firebaseFunction, char *firebasePayload, char **firebaseResponse) {
char buf[1024];
char *firebaseLocal;
char *firebaseMessage;
firebaseMessage = (char *) malloc(1024);
SSL_CTX *ctx;
int server;
SSL *ssl;
int bytes;
ctx = InitCTX();
server = OpenConnection(HOST, atoi(PORT));
ssl = SSL_new(ctx); /* create new SSL connection state */
SSL_set_fd(ssl, server); /* attach the socket descriptor */
if ( SSL_connect(ssl) == FAIL ) /* perform the connection */
ERR_print_errors_fp(stderr);
else {
ShowCerts(ssl); /* get any certs */
char *firebasePost;
generatePostMessage(firebaseFunction, firebasePayload, &firebasePost);
SSL_write(ssl, firebasePost, strlen(firebasePost));
bytes = SSL_read(ssl, buf, sizeof(buf)); /* get reply & decrypt */
buf[bytes] = 0;
//SSL_free(ssl); /* release connection state */
strcpy(firebaseMessage, buf);
firebaseLocal = strstr(firebaseMessage, "\r\n\r\n");
if (firebaseLocal != NULL) {
firebaseLocal +=4;
}
strcpy(*firebaseResponse, firebaseLocal);
}
free(firebaseMessage);
close(server); /* close socket */
SSL_CTX_free(ctx); /* release context */
return 0;
}
This is from an implementation I found on secure sockets.
int OpenConnection(const char *hostname, int port)
{ int sd;
struct hostent *host;
struct sockaddr_in addr;
if ( (host = gethostbyname(hostname)) == NULL )
{
perror(hostname);
abort();
}
sd = socket(PF_INET, SOCK_STREAM, 0);
bzero(&addr, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_port = htons(port);
addr.sin_addr.s_addr = *(long*)(host->h_addr);
if ( connect(sd, (struct sockaddr*)&addr, sizeof(addr)) != 0 )
{
close(sd);
perror(hostname);
abort();
}
return sd;
}
This is from an implementation I found on secure sockets.
SSL_CTX* InitCTX(void)
{
SSL_METHOD *method;
SSL_CTX *ctx;
SSL_library_init();
OpenSSL_add_all_algorithms(); /* Load cryptos, et.al. */
SSL_load_error_strings(); /* Bring in and register error messages */
method = TLSv1_2_client_method(); /* Create new client-method instance */
ctx = SSL_CTX_new(method); /* Create new context */
if ( ctx == NULL )
{
ERR_print_errors_fp(stderr);
abort();
}
return ctx;
}
This is from an implementation I found on secure sockets.
void ShowCerts(SSL* ssl)
{ X509 *cert;
char *line;
cert = SSL_get_peer_certificate(ssl); /* get the server's certificate */
if ( cert != NULL )
{
printf("Server certificates:\n");
line = X509_NAME_oneline(X509_get_subject_name(cert), 0, 0);
printf("Subject: %s\n", line);
free(line); /* free the malloc'ed string */
line = X509_NAME_oneline(X509_get_issuer_name(cert), 0, 0);
printf("Issuer: %s\n", line);
free(line); /* free the malloc'ed string */
X509_free(cert); /* free the malloc'ed certificate copy */
}
else
printf("Info: No client certificates configured.\n");
}
This is something that I wrote to generate a post message from message
void generatePostMessage(char *firebaseFunction, char *firebaseMessage, char **response) {
int intPayloadSize = strlen(firebaseMessage);
char *charPayloadSize;
charPayloadSize = (char *) malloc(8);
sprintf(charPayloadSize, "%d", intPayloadSize);
char *postmessage = "POST /%s HTTP/1.1\r\n"
"Host: us-central1-carconnect-e763e.cloudfunctions.net\r\n"
"User-Agent: USER_AGENT\r\n"
"Content-Type: application/json\r\n"
"Accept: text/plain\r\n"
"Content-Length: %d\r\n\r\n"
"%s";
// Allocate size of postmessage less the inserts, plus the payload size, plus the payload size digits, plus null
int responseLength = (strlen(postmessage) - 4) + intPayloadSize + strlen(charPayloadSize)+1;
// Round up Four Bytes.
int responseIncrease = responseLength % 4;
if (responseIncrease > 0) {
responseLength += (4 - responseIncrease);
}
*response = (char *) malloc(responseLength);
sprintf(*response, postmessage, firebaseFunction, intPayloadSize, firebaseMessage);
}
As advised, whether the registration or registration check is called first, the first call works fine.
If I perform the registration before the check, then both commands work fine. Further testing also does confirm the problem is the registration check. I can perform registration several times without fail. The registration check and any follow up calls fail completely at the SSL_connect line. I don't know why.
The SSL_free command in the firebase connection always fails. I also get a SIGSEGV if I try to free(firebasePost) after the SSL_Write - which suggests I cannot free a pointer that has been passed by reference and mallocced in a function.
Part of me wonders whether any of this is caused by the fact Im debugging on Windows. I've always had problems with malloc() on Windows just not working the way I would expect.
The problem, or at least one of them, is in generatePostMessage. Not enough buffer is allocated for response. sprintf will then run off the end of the allocated buffer and cause heap corruption, which manifests itself on next invocation of malloc. Try:
int responseLength = strlen(firebaseFunction) + (strlen(postmessage) - 4) + intPayloadSize + strlen(charPayloadSize)+1;

Sockets in C: recv fails after one byte

I'm currently doing an assignment in which we are defined to use send()/recv() with two parts:
first send an int that indicates the length of the string (4 bytes) and then send the string itself.
When I try to run the client/server on my PC, only the first recv() returns success, while the next one fails.
When I run the same code on my partner's PC, it works well.
The error I'm receiving for recv() is 10054.
I am totally clueless, and have no idea how to approach this.
The receiving code is:
TransferResult_t ReceiveString(char** OutputStrPtr, SOCKET sd){
/* Recv the the request to the server on socket sd */
int TotalStringSizeInBytes;
TransferResult_t RecvRes;
char* StrBuffer = NULL;
if ((OutputStrPtr == NULL) || (*OutputStrPtr != NULL))
{
printf("The first input to ReceiveString() must be "
"a pointer to a char pointer that is initialized to NULL. For example:\n"
"\tchar* Buffer = NULL;\n"
"\tReceiveString( &Buffer, ___ )\n");
return TRNS_FAILED;
}
/* The request is received in two parts. First the Length of the string (stored in
an int variable ), then the string itself. */
RecvRes = ReceiveBuffer(
(char *)(&TotalStringSizeInBytes),
(int)(sizeof(TotalStringSizeInBytes)), // 4 bytes
sd);
if (RecvRes != TRNS_SUCCEEDED) return RecvRes;
StrBuffer = (char*)malloc(TotalStringSizeInBytes * sizeof(char));
if (StrBuffer == NULL)
return TRNS_FAILED;
RecvRes = ReceiveBuffer(
(char *)(StrBuffer),
(int)(TotalStringSizeInBytes),
sd);
if (RecvRes == TRNS_SUCCEEDED)
{
*OutputStrPtr = StrBuffer;
}
else
{
free(StrBuffer);
}
return RecvRes;
}
The ReceiveBuffer function is:
TransferResult_t ReceiveBuffer(char* OutputBuffer, int BytesToReceive, SOCKET sd){
char* CurPlacePtr = OutputBuffer;
int BytesJustTransferred;
int RemainingBytesToReceive = BytesToReceive;
while (RemainingBytesToReceive > 0)
{
/* send does not guarantee that the entire message is sent */
BytesJustTransferred = recv(sd, CurPlacePtr, RemainingBytesToReceive, 0);
if (BytesJustTransferred == SOCKET_ERROR)
{
printf("recv() failed, error %d\n", WSAGetLastError());
return TRNS_FAILED;
}
else if (BytesJustTransferred == 0)
return TRNS_DISCONNECTED; // recv() returns zero if connection was gracefully disconnected.
RemainingBytesToReceive -= BytesJustTransferred;
CurPlacePtr += BytesJustTransferred; // <ISP> pointer arithmetic
}
return TRNS_SUCCEEDED;
}
ADDED: the sending function:
TransferResult_t SendString( const char *Str, SOCKET sd ){
/* Send the the request to the server on socket sd */
int TotalStringSizeInBytes;
TransferResult_t SendRes;
/* The request is sent in two parts. First the Length of the string (stored in
an int variable ), then the string itself. */
TotalStringSizeInBytes = (int)( strlen(Str) + 1 ); // terminating zero also sent
SendRes = SendBuffer(
(const char *)( &TotalStringSizeInBytes ),
(int)( sizeof(TotalStringSizeInBytes) ), // sizeof(int)
sd );
if ( SendRes != TRNS_SUCCEEDED ) return SendRes ;
SendRes = SendBuffer(
(const char *)( Str ),
(int)( TotalStringSizeInBytes ),
sd );
return SendRes;
}
And:
TransferResult_t SendBuffer( const char* Buffer, int BytesToSend, SOCKET sd ){
const char* CurPlacePtr = Buffer;
int BytesTransferred;
int RemainingBytesToSend = BytesToSend;
while ( RemainingBytesToSend > 0 )
{
/* send does not guarantee that the entire message is sent */
BytesTransferred = send (sd, CurPlacePtr, RemainingBytesToSend, 0);
if ( BytesTransferred == SOCKET_ERROR )
{
printf("send() failed, error %d\n", WSAGetLastError() );
return TRNS_FAILED;
}
RemainingBytesToSend -= BytesTransferred;
CurPlacePtr += BytesTransferred; // <ISP> pointer arithmetic
}
return TRNS_SUCCEEDED;
}

My try to write unix domain socket communication script between Ruby and C

I am trying to make a bridge via unix domain socket between Ruby script as server and C app as client but currently I am stuck in the read loop until I kill Ruby script maybe someone could look at the code?
struct sockaddr_un addr;
int fd,rc;
char *socket_path = "/tmp/auth.sock";
char *output_packet = cern_format_packet(pw, key);
if ( (fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {
error("socket error");
return 0;
}
memset(&addr, 0, sizeof(addr));
addr.sun_family = AF_UNIX;
strncpy(addr.sun_path, socket_path, sizeof(addr.sun_path)-1);
if (connect(fd, (struct sockaddr*)&addr, sizeof(addr)) == -1) {
error("connect error");
return 0;
}
logit("cern_output: %s", output_packet);
write(fd, output_packet, strlen(output_packet));
#define BUFFERSIZE 1024
#define MAXDATASIZE 256
int c, q = 0, success;
char* input_buffer;
char data_buffer[MAXDATASIZE];
size_t input_buffer_size = BUFFERSIZE;
input_buffer = malloc(input_buffer_size);
if (input_buffer)
{
while((c = read(fd, data_buffer, MAXDATASIZE)) > 0)
{
if (c + q > input_buffer_size)
{
input_buffer_size *= 2; /* Arbitrary doubling of size. */
char* tmp = realloc(input_buffer, input_buffer_size);
if (tmp)
{
input_buffer = tmp;
}
else
{
/* memory allocation failure. */
free(input_buffer);
input_buffer = 0;
break;
}
}
memcpy(input_buffer + q, data_buffer, c);
q += c;
}
}
json_error_t error;
json_t *root = json_loads( input_buffer, 0, &error );
if (root) {
json_t *json_status = json_object_get( root, "status" );
json_t *json_command = json_object_get( root, "command" );
const char *return_comamnd = json_string_value( json_command );
success = (int)json_integer_value(json_status);
logit("json_response: status: %i command: %s",success, return_comamnd);
}
close(fd);
return success;
And the ruby script
require "socket"
require 'msgpack'
require "json"
file = "/tmp/auth.sock"
File.unlink if File.exists?(file) && File.socket?(file)
serv = UNIXServer.new(file)
loop do
s = serv.accept
msg = s.gets
msg = msg.gsub("\n", "") if msg
p JSON.parse(msg)
a = {}
a["status"] = 1
a["command"] = "hello world"
s.write(JSON.generate(a))
s.close
end
The client's call to read() most likely blocks because the server did send less then the client was told to read, that is MAXDATASIZE bytes.
Do get around this let the server orderly shutdown the socket before closing it.
I'm no Ruby expert but may be something like:
s.shutdown
s.close
would do the job.
Also in the server this line:
msg = s.gets
might block until a \n had been received. (See here for details on gets: http://www.ruby-doc.org/core-2.0.0/IO.html#method-i-gets)

Getaddrinfo issue in C

I'm working on a proxy application in C for a project. I have an issue with getaddrinfo() being unsuccessful when I pass it the parsed host name. If I hard code the host, for example "www.google.ca" it doesn't error but when given the URL (from a GET request that the code receives) it does produce an error (The exact error is "Unknown name or service"). I've tried debugging in NetBeans and as far as I can tell the parsed URL is no different from the one I've hard coded. Below is the code that I'm using:
Snippet of code that receives the request and tries to forward it:
...
//Message is received in the code before this
if (get_host(message, &url) == 0)
{
//Tries to open a socket to the parsed URL. This is where the issue happens
forawrd_fd = create_forward_socket(url, "80");
}
...
The get host function:
int get_host(char *request, char **host_url)
{
char url[BUFFER_SIZE];
if(sscanf(request, "%*s %s HTTP/1.1\r\n", url) != 1)
{
return -1;
}
else
{
int len = strlen(url);
//If there is a / at the end of the URL remove it
if(url[len-1] == '/')
{
printf("%c%c\n", url[len-2], url[len-1]);
url[len-1] = '\0';
printf("%s\n", url);
}
*host_url = &url;
//If the start of the string is http:// remove it
if(url[0] == 'h' && url[1] == 't' && url[2] == 't'&& url[3] == 'p')
{
*host_url += 7;
}
return 0;
}
}
Function that gets the file descriptor and makes the getaddrinfo
int create_forward_socket(char* url, const char* port)
{
//Status variable needed for some calls
int status, socket_fd, received_data;
//Setup address info structs
struct addrinfo hints;
struct addrinfo *result, *current;
//Initialize our hints.
memset(&hints, 0, sizeof hints);
//IPv4 or IPv6 we don't
hints.ai_family = AF_UNSPEC;
//We want a stream socket not datagram
hints.ai_socktype = SOCK_STREAM;
//Whatever this means (I forget but again the interwebs says...)
hints.ai_flags = AI_PASSIVE;
//Get a linked list of address info that we will choose from
if ((status = getaddrinfo(url, port, &hints, &result)) != 0) //Status here is -2 when called with the parsed URL
{
return -1;
}
for (current = result; current != NULL; current = current->ai_next)
{
if ((socket_fd = socket(current->ai_family, current->ai_socktype, current->ai_protocol)) != -1)
{
if (connect(socket_fd, current->ai_addr, current->ai_addrlen) != -1)
{
//We found a usable socket
break;
}
else
{
close(socket_fd);
}
}
}
if (current == NULL)
{
return -2;
}
else
{
return socket_fd;
}
}
Any help would be appreciated. If more of my code is needed please let me know. I included only what I thought was important so the post wasn't too long.
My guess is that you are returning a pointer to a local variable. See, url is a local variable, and the *host_url = url; line (I'm assuming that this is an output parameter) will return it to the caller. But local variables will be destroyed just when the function returns, and then, *host_url will point to the middle of nowhere.
The code calling get_host() is like:
char *host;
get_host(req, &host);
//call getaddrinfo with host
But host will not point to valid memory outside of get_host.
The solution is that the caller allocates the buffer:
int get_host(char *request, char *url)
{ ... }
And when you call it:
char host[BUFFER_SIZE];
get_host(req, host);
//call getaddrinfo with host

Resources