Doing some research on high performance TCP server (not necessarily for HTTP) for testing purpose. Followed some sample code and created a libuv based TCP server, however the following sample code will crash with error SIGPIPE on the line uv_write(req, stream, buffer, 1, on_write);. Here is the console output:
client=0x562529924700
1writing to 0x562529924700
2writing to 0x562529924700
wrote.
1writing to 0x562529924700
Note that the tcp client closes the first tcp connection with TCP RESET. Wireshark shows that the TCP client has established the second tcp connection and sent the request, but the tcp server somehow didn't print something similar to the line client=0x562529924700 to indicate that it has accept the second connection.
Any ideas would be appreciated.
Here is the server code
//from https://gist.github.com/Jxck/4305806
// https://nikhilm.github.io/uvbook/networking.html
//api guide http://docs.libuv.org/en/v1.x/
#include <stdio.h>
#include <stdlib.h>
#include <uv.h>
#include <string.h>
#include <unistd.h>
#define DEFAULT_PORT 8080
#define DEFAULT_BACKLOG 1000
uv_loop_t *loop;
int cnt = 0;
char *str = "HTTP/1.1 200 Ok\r\nContent-Length: 7\r\n\r\n%07d\n";
void on_write(uv_write_t* req, int status)
{
if (status) {
perror( "uv_write error ");
return;
}
printf("wrote.\n");
free(req);
//uv_close((uv_handle_t*)req->handle, on_close);
}
void write2(uv_stream_t* stream, char *data, int len2) {
uv_buf_t buffer[] = {
{.base = data, .len = len2}
};
uv_write_t *req = malloc(sizeof(uv_write_t));
printf("1writing to %p\n", stream);
uv_write(req, stream, buffer, 1, on_write);
printf("2writing to %p\n", stream);
}
void on_close(uv_handle_t* handle)
{
//printf("closed.");
}
void echo_read(uv_stream_t *sock, ssize_t nread, const uv_buf_t *buf) {
if (nread == -1) {
fprintf(stderr, "error echo_read");
return;
} else if (nread == 0) {
uv_close((uv_handle_t*)sock, on_close);
return;
}
char respMsg[52];
sprintf(respMsg, str, cnt++);
//snprintf(&respMsg[41], 6,"%6d", cnt++);
write2(sock, respMsg, strlen(respMsg));
//printf("result: %s\n", buf->base);
}
static void my_alloc_cb(uv_handle_t* handle, size_t suggested_size, uv_buf_t* buf) {
buf->base = malloc(suggested_size);
buf->len = suggested_size;
}
void on_new_connection(uv_stream_t *server, int status) {
if (status < 0) {
fprintf(stderr, "New connection error %s\n", uv_strerror(status));
// error!
return;
}
uv_tcp_t *client = (uv_tcp_t*) malloc(sizeof(uv_tcp_t));
printf("client=%p\n", client);
uv_tcp_init(loop, client);
if (uv_accept(server, (uv_stream_t*) client) == 0) {
uv_read_start((uv_stream_t*) client, my_alloc_cb, echo_read);
}
else {
printf("failed to accept\n");
uv_close((uv_handle_t*) client, NULL);
}
}
int main() {
loop = uv_default_loop();
uv_tcp_t server;
uv_tcp_init(loop, &server);
struct sockaddr_in addr;
uv_ip4_addr("0.0.0.0", DEFAULT_PORT, &addr);
int r;
r = uv_tcp_bind(&server, (const struct sockaddr*)&addr, 0);
r = uv_listen((uv_stream_t*) &server, DEFAULT_BACKLOG, on_new_connection);
if (r) {
fprintf(stderr, "Listen error %s\n", uv_strerror(r));
return 1;
}
return uv_run(loop, UV_RUN_DEFAULT);
}
Turned out the issue is on echo_read(). When the TCP connection is terminated with tcp reset, nread is not -1, it's some negative number (-4095 in my case).
Was able to take care of it using nread < 0 instead of nread == -1.
void echo_read(uv_stream_t *sock, ssize_t nread, const uv_buf_t *buf) {
if (nread == -1) {
fprintf(stderr, "error echo_read");
return;
} else if (nread == 0) {
uv_close((uv_handle_t*)sock, on_close);
return;
}
Related
The TCP Echo Server sample from the Azure Sphere Samples at github works great and I am able to use my PC or a raspberryPi as a TCP client and communicate to the TCP echo server at the sphere device. However, I have a requirement where I need my Azure Sphere device as a TCP client. I modified the private network services sample application to work as a client (commented out Echo TCP Server) but the connection to the TCP server running at PC fails. The 'connect' returns -1 with errno set to 115 (ERROR: Operation in progress). I have configured the network services at azure sphere device with static ip. I have also verified that the same TCP client and server application works fine when a raspberrypi is used as a client and PC as the server. This is the modified main file of the application:
#include <errno.h>
#include <signal.h>
#include <stdbool.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
#include <arpa/inet.h>
#include "applibs_versions.h"
#include <applibs/log.h>
#include <applibs/networking.h>
#include <hw/sample_hardware.h>
typedef enum {
ExitCode_Success = 0,
ExitCode_TermHandler_SigTerm = 1,
ExitCode_StoppedHandler_Stopped = 2,
ExitCode_CheckStatus_SetInterfaceState = 3,
ExitCode_CheckStatus_GetInterfaceCount = 4,
ExitCode_CheckStatus_GetInterfaceConnectionStatus = 5,
ExitCode_ConfigureStaticIp_IpConfigApply = 6,
ExitCode_StartSntpServer_StartSntp = 7,
ExitCode_StartDhcpServer_StartDhcp = 8,
ExitCode_TimerHandler_Consume = 9,
ExitCode_InitLaunch_Epoll = 10,
ExitCode_InitLaunch_Timer = 11,
ExitCode_Main_WaitCallFailure = 12,
ExitCode_EchoStart_Listen = 13,
ExitCode_OpenIpV4_Socket = 14,
ExitCode_OpenIpV4_SetSockOpt = 15,
ExitCode_OpenIpV4_Bind = 16
} ExitCode;
int tcp_client(void);
static bool isNetworkStackReady = false;
static volatile sig_atomic_t exitCode = ExitCode_Success;
static struct in_addr localServerIpAddress;
static struct in_addr subnetMask;
static struct in_addr gatewayIpAddress;
static const uint16_t LocalTcpServerPort = 11000;
static int serverBacklogSize = 3;
static const char NetworkInterface[] = "eth0";
int tcp_client(void) {
int sock = 0, valread;
struct sockaddr_in serv_addr;
char* hello = "Hello from client";
char buffer[1024] = { 0 };
if ((sock = socket(AF_INET, SOCK_STREAM | SOCK_NONBLOCK, 0)) < 0)
{
Log_Debug("\n Socket creation error \n");
return -1;
}
Log_Debug("TCP_CLIENT: socket created\n");
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(8080);
if (inet_pton(AF_INET, "169.254.57.67", &serv_addr.sin_addr) <= 0)
{
Log_Debug("\nInvalid address/ Address not supported \n");
return -1;
}
Log_Debug("TCP_CLIENT: ip assigned\n");
int conn = connect(sock, (struct sockaddr*) & serv_addr, sizeof(serv_addr));
Log_Debug("TCP_CLIENT: conn = %d\n", conn);
Log_Debug("ERROR: %s\n", strerror(errno));
if (conn < 0)
{
Log_Debug("\nConnection Failed \n");
return -1;
}
send(sock, hello, strlen(hello), 0);
Log_Debug("Hello message sent\n");
valread = read(sock, buffer, 1024);
Log_Debug("%s\n", buffer);
return 0;
}
static ExitCode CheckNetworkStatus(void)
{
int result = Networking_SetInterfaceState(NetworkInterface, true);
if (result != 0) {
if (errno == EAGAIN) {
Log_Debug("INFO: The networking stack isn't ready yet, will try again later.\n");
return ExitCode_Success;
} else {
Log_Debug(
"ERROR: Networking_SetInterfaceState for interface '%s' failed: errno=%d (%s)\n",
NetworkInterface, errno, strerror(errno));
return ExitCode_CheckStatus_SetInterfaceState;
}
}
Log_Debug("INFO: CheckNetworkStatus: Network stack is ready\n");
isNetworkStackReady = true;
ssize_t count = Networking_GetInterfaceCount();
if (count == -1) {
Log_Debug("ERROR: Networking_GetInterfaceCount: errno=%d (%s)\n", errno, strerror(errno));
return ExitCode_CheckStatus_GetInterfaceCount;
}
Log_Debug("INFO:CheckNetworkStatus: Networking_GetInterfaceCount: count=%zd\n", count);
// Read current status of all interfaces.
size_t bytesRequired = ((size_t)count) * sizeof(Networking_NetworkInterface);
Networking_NetworkInterface *interfaces = malloc(bytesRequired);
if (!interfaces) {
abort();
}
ssize_t actualCount = Networking_GetInterfaces(interfaces, (size_t)count);
if (actualCount == -1) {
Log_Debug("ERROR: Networking_GetInterfaces: errno=%d (%s)\n", errno, strerror(errno));
}
Log_Debug("INFO: Networking_GetInterfaces: actualCount=%zd\n", actualCount);
for (ssize_t i = 0; i < actualCount; ++i) {
Log_Debug("INFO: interface #%zd\n", i);
Log_Debug("INFO: interfaceName=\"%s\"\n", interfaces[i].interfaceName);
Log_Debug("INFO: isEnabled=\"%d\"\n", interfaces[i].isEnabled);
Networking_IpType ipType = interfaces[i].ipConfigurationType;
const char *typeText;
switch (ipType) {
case Networking_IpType_DhcpNone:
typeText = "DhcpNone";
break;
case Networking_IpType_DhcpClient:
typeText = "DhcpClient";
break;
default:
typeText = "unknown-configuration-type";
break;
}
Log_Debug("INFO: ipConfigurationType=%d (%s)\n", ipType, typeText);
Networking_InterfaceMedium_Type mediumType = interfaces[i].interfaceMediumType;
const char *mediumText;
switch (mediumType) {
case Networking_InterfaceMedium_Unspecified:
mediumText = "unspecified";
break;
case Networking_InterfaceMedium_Wifi:
mediumText = "Wi-Fi";
break;
case Networking_InterfaceMedium_Ethernet:
mediumText = "Ethernet";
break;
default:
mediumText = "unknown-medium";
break;
}
Log_Debug("INFO: interfaceMediumType=%d (%s)\n", mediumType, mediumText);
Networking_InterfaceConnectionStatus status;
int result = Networking_GetInterfaceConnectionStatus(interfaces[i].interfaceName, &status);
if (result != 0) {
Log_Debug("ERROR: Networking_GetInterfaceConnectionStatus: errno=%d (%s)\n", errno,
strerror(errno));
return ExitCode_CheckStatus_GetInterfaceConnectionStatus;
}
Log_Debug("INFO: interfaceStatus=0x%02x\n", status);
}
free(interfaces);
return ExitCode_Success;
}
static ExitCode ConfigureNetworkInterfaceWithStaticIp(const char *interfaceName)
{
Networking_IpConfig ipConfig;
Log_Debug("INFO: ConfigureNetworkInterfaceWithStaticIp: %s.\n", interfaceName);
Networking_IpConfig_Init(&ipConfig);
inet_aton("169.254.57.70", &localServerIpAddress);
inet_aton("255.255.0.0", &subnetMask);
inet_aton("0.0.0.0", &gatewayIpAddress);
Networking_IpConfig_EnableStaticIp(&ipConfig, localServerIpAddress, subnetMask,
gatewayIpAddress);
int result = Networking_IpConfig_Apply(interfaceName, &ipConfig);
Networking_IpConfig_Destroy(&ipConfig);
if (result != 0) {
Log_Debug("ERROR: Networking_IpConfig_Apply: %d (%s)\n", errno, strerror(errno));
return ExitCode_ConfigureStaticIp_IpConfigApply;
}
Log_Debug("INFO: Set static IP address on network interface: %s.\n", interfaceName);
return ExitCode_Success;
}
static ExitCode init_nw_services(void)
{
// Check the network stack readiness and display available interfaces when it's ready.
Log_Debug("INFO: Inside init_nw_services\n");
ExitCode localExitCode = CheckNetworkStatus();
if (localExitCode != ExitCode_Success) {
return localExitCode;
}
if (isNetworkStackReady) {
Log_Debug("INFO: init_nw_services: The network stack is ready, so unregister the timer event handler and launch servers.\n");
localExitCode = ConfigureNetworkInterfaceWithStaticIp(NetworkInterface);
}
return ExitCode_Success;
}
static ExitCode initialize_nw(void)
{
while (!isNetworkStackReady) {
if (!isNetworkStackReady) {
Log_Debug("INFO: init_nw_services\n");
ExitCode localExitCode = init_nw_services();
if (localExitCode != ExitCode_Success) {
exitCode = localExitCode;
return;
}
}
else {
Log_Debug("INFO: Network stack is ready\n");
}
}
Log_Debug("INFO: Initialization and server launch complete\n");
return ExitCode_Success;
}
int main(int argc, char *argv[])
{
Log_Debug("INFO: Private Ethernet TCP server application starting.\n");
exitCode = initialize_nw();
if (isNetworkStackReady)
tcp_client();
Log_Debug("INFO: Application exiting.\n");
return exitCode;
}
Yes this is possible. Please ensure that the destination is in the app manifest under AllowedConnections
My platform:
Ubuntu 17.10 32-bit (Vbox VM)
Qt Creator 3.5.1 (opensource)
Qt 5.5.1 (GCC 4.9.1 20140922 (Red Hat 4.9.1-10), 32 bit
I am trying to invoke a multithreaded program (with arguments) using QProcess.start().
My program runs fine on terminal, i.e. periodically prints on stdout.
Using a TextEdit to log the stdout/stderr of the program I have connected QProcess readyReadStandardOutput/Error signals.
The stdout/stderr that comes from the main thread of the program is correctly shown on the TextEdit, the rest of the output (the one from all the other threads) is not shown.
EDIT
On the main thread an HTTP server is listening.
If a HTTP request is performed by browser at the url "127.0.0.1:32001" (port 32001 is hard coded in the QT code), when the HTTP request is received the program appends the HTTP packet and all the pending output from the other thread (moduleThread) to the TextEdit, so it could be a problem of flushing.
main.c
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <pthread.h>
#include <semaphore.h>
#include <sys/time.h>
#include <sys/signal.h>
#include <sys/stat.h>
#include <sys/types.h>
#include "http_server.h"
static pthread_t moduleThr;
static pthread_attr_t moduleThread_attr;
static bool one_second_elapsed;
static sem_t oneSecondSem;
void *moduleThread(void *arg0)
{
bool one_second_elapsed_local;
while (1)
{
sem_wait(&oneSecondSem);
one_second_elapsed_local = one_second_elapsed;
one_second_elapsed = false;
sem_post(&oneSecondSem);
if (one_second_elapsed_local)
fprintf(stdout, "Hello world each second!\r\n");
usleep(50000);
}
}
static void oneSecElapsed(int signum)
{
sem_wait(&oneSecondSem);
one_second_elapsed = true;
sem_post(&oneSecondSem);
}
static void TIMER_1sec_init(void)
{
struct sigaction sa;
struct itimerval timer;
/* Install timer_handler as the signal handler for SIGALRM. */
memset (&sa, 0, sizeof (sa));
sa.sa_handler = &oneSecElapsed;
sigaction (SIGALRM, &sa, NULL);
/* Configure the timer to expire after 1 sec... */
timer.it_value.tv_sec = 1;
timer.it_value.tv_usec = 0;
/* ... and every 1 sec after that... */
timer.it_interval.tv_sec = 1;
timer.it_interval.tv_usec = 0;
/* Start a virtual timer. It counts down whenever this process is
executing. */
setitimer (ITIMER_REAL, &timer, NULL);
}
/*
* ======== main ========
*/
int main(int argc, char *argv[])
{
const char *tcpport;
if (argc > 2)
{
fprintf(stdout, "id = %s\r\n", argv[1]);
fprintf(stdout, "tcpport = %s\r\n", argv[2]);
tcpport = argv[2];
}
else
exit(-1);
sem_init(&oneSecondSem, 0, 1);
one_second_elapsed = false;
/* Create thread quadro manager */
pthread_attr_init(&moduleThread_attr);
pthread_attr_setstacksize(&moduleThread_attr, 2048);
pthread_create(&moduleThr, &moduleThread_attr, moduleThread, NULL);
TIMER_1sec_init();
HTTPSERVER_init(tcpport);
/* should never return */
return (0);
}
http_server.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h> /* memset() */
#include <stdbool.h>
#include <signal.h>
#include <sys/socket.h>
#include <sys/signal.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <netdb.h>
#include "module.h"
typedef struct { char *name, *value; } header_t;
static header_t reqhdr[17] = { {"\0", "\0"} };
//#define PORT "32001" /* Port to listen on */
#define BACKLOG 10 /* Passed to listen() */
static char *buf;
static char *method; // "GET" or "POST"
static char *uri; // "/index.html" things before '?'
static char *qs; // "a=1&b=2" things after '?'
static char *prot; // "HTTP/1.1"
static char *payload; // for POST
static int payload_size;
// get request header
char *request_header(const char* name)
{
header_t *h = reqhdr;
while(h->name) {
if (strcmp(h->name, name) == 0) return h->value;
h++;
}
return NULL;
}
void handle(int newsock)
{
//static int count = 0;
/* recv(), send(), close() */
int rcvd;
buf = malloc(65535);
rcvd=recv(newsock, buf, 65535, 0);
if (rcvd<0) // receive error
fprintf(stderr,("recv() error\n"));
else if (rcvd==0) // receive socket closed
fprintf(stderr,"Client disconnected unexpectedly.\n");
else // message received
{
buf[rcvd] = '\0';
//fputs(buf, stdout);
//fprintf(stdout, "count = %d\n", count);
method = strtok(buf, " \t\r\n");
uri = strtok(NULL, " \t");
prot = strtok(NULL, " \t\r\n");
fprintf(stderr, "\x1b[32m + [%s] %s\x1b[0m\n", method, uri);
if ((qs = strchr(uri, '?')))
{
*qs++ = '\0'; //split URI
} else {
qs = uri - 1; //use an empty string
}
header_t *h = reqhdr;
char *t = (char *)reqhdr;
char *t2;
while(h < reqhdr+16) {
char *k,*v;
k = strtok(NULL, "\r\n: \t");
if (!k)
break;
v = strtok(NULL, "\r\n");
while(*v && *v==' ')
v++;
h->name = k;
h->value = v;
h++;
fprintf(stderr, "[H] %s: %s\n", k, v);
t = v + 1 + strlen(v);
if (t[1] == '\r' && t[2] == '\n')
break;
}
t+=2;
t++; // now the *t shall be the beginning of user payload
t2 = request_header("content-length"); // and the related header if there is
payload = t;
payload_size = t2 ? atol(t2) : (rcvd-(t-buf));
fprintf(stdout, "-- payload len = %d >", payload_size);
fputs(payload, stdout);
fprintf(stdout, "<\r\n");
if (strcmp(method, "GET") == 0)
{
fprintf(stdout, "\nit's a GET!\r\n");
}
else if (strcmp(method, "POST") == 0)
{
fprintf(stdout, "\nit's a POST!\r\n");
}
sprintf(buf, "HTTP/1.1 200 OK\r\n\r\n");
send(newsock, buf, strlen(buf), 0);
close(newsock);
free(buf);
}
}
int HTTPSERVER_init(const char *tcpport)
{
int sock;
struct addrinfo hints, *res;
int reuseaddr = 1; /* True */
sigset_t sigset, oldset;
sigfillset(&sigset);
pthread_sigmask(SIG_BLOCK, &sigset, &oldset);
/* Get the address info */
memset(&hints, 0, sizeof hints);
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
if (getaddrinfo(NULL, tcpport, &hints, &res) != 0) {
perror("getaddrinfo");
return 1;
}
/* Create the socket */
sock = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
if (sock == -1) {
perror("socket");
return 1;
}
/* Enable the socket to reuse the address */
if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &reuseaddr, sizeof(int)) == -1) {
perror("setsockopt");
return 1;
}
/* Bind to the address */
if (bind(sock, res->ai_addr, res->ai_addrlen) == -1) {
perror("bind");
return 1;
}
/* Listen */
if (listen(sock, BACKLOG) == -1) {
perror("listen");
return 1;
}
freeaddrinfo(res);
/* Main loop */
while (1) {
printf("waiting on accept\n");
fflush(stdout);
socklen_t size = sizeof(struct sockaddr_in);
struct sockaddr_in their_addr;
int newsock = accept(sock, (struct sockaddr*)&their_addr, &size);
if (newsock == -1) {
perror("accept");
}
else {
printf("Got a connection from %s on port %d\n",
inet_ntoa(their_addr.sin_addr), htons(their_addr.sin_port));
handle(newsock);
}
}
close(sock);
return 0;
}
As pointed out by #eyllanesc, the pending strings "Hello world each second!\r\n" come out eventually after several seconds.
The moduleThread shoud be a thread and not a different process: this is verified by commadn "ps aux" that shows only "../program/testApp test 32001".
Could any of you kindly give me a hint on what is going on here please?
Thanks for your time,
Francesco
Hi I am new to working with openssl, i am trying to implement anonymous Diffie Hellman connection using openssl.
The code server code looks some thing like this:
#include "openssl/err.h"
#include "openssl/ssl.h"
#include "openssl/dh.h"
#include <arpa/inet.h>
#include <errno.h>
#include <malloc.h>
#include <netinet/in.h>
#include <resolv.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <unistd.h>
#define FAIL -1
// Create the SSL socket and intialize the socket address structure
int OpenListener(int port) {
int sd;
struct sockaddr_in addr;
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 = INADDR_ANY;
if (bind(sd, (struct sockaddr *)&addr, sizeof(addr)) != 0) {
perror("can't bind port");
abort();
}
if (listen(sd, 10) != 0) {
perror("Can't configure listening port");
abort();
}
return sd;
}
int isRoot() {
if (getuid() != 0) {
return 0;
} else {
return 1;
}
}
SSL_CTX *InitServerCTX(void) {
SSL_METHOD *method;
SSL_CTX *ctx;
DH *dh_;
int codes = 0;
OpenSSL_add_all_algorithms(); /* load & register all cryptos, etc. */
SSL_load_error_strings(); /* load all error messages */
method = TLSv1_2_server_method(); /* create new server-method instance */
ctx = SSL_CTX_new(method); /* create new context from method */
if (ctx == NULL) {
ERR_print_errors_fp(stderr);
abort();
}
if (SSL_CTX_set_cipher_list(ctx, "ADH-AES256-SHA256") != 1) {
ERR_print_errors_fp(stderr);
abort();
}
dh_ = DH_new();
if (dh_ == NULL) {
printf ("Alloc for dh failed\n");
ERR_print_errors_fp(stderr);
abort();
}
// Generate Parameters.
if (!DH_generate_parameters_ex (dh_, 1024, DH_GENERATOR_5, NULL)) {
printf ("Generate Parameters failed!!\n");
ERR_print_errors_fp(stderr);
abort();
ERR_print_errors_fp(stderr);
}
// Check if p and g parameters are safe to use.
if (!DH_check (dh_, &codes)) {
printf ("Cannot perform DH check\n");
ERR_print_errors_fp(stderr);
abort();
}
if (codes) {
printf ("DH codes: %x\n", codes);
ERR_print_errors_fp(stderr);
abort();
}
if (!DH_generate_key (dh_)) {
printf ("Failure in DH Generate key\n");
ERR_print_errors_fp(stderr);
abort();
}
SSL_CTX_set_tmp_dh(ctx, dh_);
DH_free(dh_);
return ctx;
}
void Servlet(SSL *ssl) /* Serve the connection -- threadable */
{
char buf[1024] = {0};
int sd, bytes;
const char *ServerResponse = "<\Body>\
<Name>aticleworld.com</Name>\
<year>1.5</year>\
<BlogType>Embedede and c\c++<\BlogType>\
<Author>amlendra<Author>\
<\Body>";
const char *cpValidMessage = "<Body>\
<UserName>aticle<UserName>\
<Password>123<Password>\
<\Body>";
if (SSL_accept(ssl) == FAIL) /* do SSL-protocol accept */
ERR_print_errors_fp(stderr);
else {
//ShowCerts(ssl); /* get any certificates */
bytes = SSL_read(ssl, buf, sizeof(buf)); /* get request */
buf[bytes] = '\0';
printf("Client msg: \"%s\"\n", buf);
if (bytes > 0) {
if (strcmp(cpValidMessage, buf) == 0) {
SSL_write(ssl, ServerResponse, strlen(ServerResponse)); /* send reply */
} else {
SSL_write(ssl, "Invalid Message",
strlen("Invalid Message")); /* send reply */
}
} else {
ERR_print_errors_fp(stderr);
}
}
sd = SSL_get_fd(ssl); /* get socket connection */
SSL_free(ssl); /* release SSL state */
close(sd); /* close connection */
}
int main(int count, char *Argc[]) {
SSL_CTX *ctx;
int server;
char *portnum;
// Only root user have the permsion to run the server
if (!isRoot()) {
printf("This program must be run as root/sudo user!!");
exit(0);
}
if (count != 2) {
printf("Usage: %s <portnum>\n", Argc[0]);
exit(0);
}
// Initialize the SSL library
SSL_library_init();
portnum = Argc[1];
ctx = InitServerCTX(); /* initialize SSL */
server = OpenListener(atoi(portnum)); /* create server socket */
while (1) {
struct sockaddr_in addr;
socklen_t len = sizeof(addr);
SSL *ssl;
int client = accept(server, (struct sockaddr *)&addr,
&len); /* accept connection as usual */
printf("Connection: %s:%d\n", inet_ntoa(addr.sin_addr),
ntohs(addr.sin_port));
ssl = SSL_new(ctx); /* get new SSL state with context */
SSL_set_fd(ssl, client); /* set connection socket to SSL state */
Servlet(ssl); /* service connection */
}
close(server); /* close server socket */
SSL_CTX_free(ctx); /* release context */
}
The client program looks like this:
#include <errno.h>
#include <malloc.h>
#include <netdb.h>
#include <openssl/err.h>
#include <openssl/ssl.h>
#include <openssl/dh.h>
#include <resolv.h>
#include <stdio.h>
#include <string.h>
#include <sys/socket.h>
#include <unistd.h>
#define FAIL -1
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);
printf ("Connecting....\n");
if (connect(sd, (struct sockaddr *)&addr, sizeof(addr)) != 0) {
close(sd);
perror(hostname);
abort();
} else {
printf ("Connected...\n");
}
return sd;
}
SSL_CTX *InitCTX(void) {
SSL_METHOD *method;
SSL_CTX *ctx;
DH *dh_;
int codes = 0;
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();
}
if (SSL_CTX_set_cipher_list(ctx, "ADH-AES256-SHA256") != 1) {
printf("SSL_CTX_set_cipher_list failed\n");
SSL_CTX_free (ctx);
ctx = NULL;
ERR_print_errors_fp(stderr);
abort();
}
dh_ = DH_new();
if (dh_ == NULL) {
printf ("Alloc for dh failed\n");
}
// Generate Parameters.
if (!DH_generate_parameters_ex (dh_, 1024, DH_GENERATOR_5, NULL)) {
printf ("Generate Parameters failed!!\n");
}
// Check if p and g parameters are safe to use.
if (!DH_check (dh_, &codes)) {
printf ("Cannot perform DH check\n");
}
if (codes) {
printf ("DH codes: %x\n", codes);
}
if (!DH_generate_key (dh_)) {
printf ("Failure in DH Generate key\n");
//retVal = false;
//break;
}
SSL_CTX_set_tmp_dh(ctx, dh_);
DH_free(dh_);
return ctx;
}
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");
}
int main(int count, char *strings[]) {
SSL_CTX *ctx;
int server;
SSL *ssl;
char buf[1024];
char acClientRequest[1024] = {0};
int bytes;
char *hostname, *portnum;
if (count != 3) {
printf("usage: %s <hostname> <portnum>\n", strings[0]);
exit(0);
}
SSL_library_init();
hostname = strings[1];
portnum = strings[2];
ctx = InitCTX();
server = OpenConnection(hostname, atoi(portnum));
ssl = SSL_new(ctx); /* create new SSL connection state */
SSL_set_fd(ssl, server); /* attach the socket descriptor */
printf ("Before connect\n");
if (SSL_connect(ssl) == FAIL) /* perform the connection */
ERR_print_errors_fp(stderr);
else {
char acUsername[16] = {0};
char acPassword[16] = {0};
const char *cpRequestMessage = "<Body>\
<UserName>%s<UserName>\
<Password>%s<Password>\
<\Body>";
printf("Enter the User Name : ");
scanf("%s", acUsername);
printf("\n\nEnter the Password : ");
scanf("%s", acPassword);
sprintf(acClientRequest, cpRequestMessage, acUsername,
acPassword); /* construct reply */
printf("\n\nConnected with %s encryption\n", SSL_get_cipher(ssl));
ShowCerts(ssl); /* get any certs */
SSL_write(ssl, acClientRequest,
strlen(acClientRequest)); /* encrypt & send message */
bytes = SSL_read(ssl, buf, sizeof(buf)); /* get reply & decrypt */
buf[bytes] = 0;
printf("Received: \"%s\"\n", buf);
SSL_free(ssl); /* release connection state */
}
close(server); /* close socket */
SSL_CTX_free(ctx); /* release context */
return 0;
}
When i compile and execute this code i get the following error:
server side:
140093403805344:error:140940E5:SSL routines:SSL3_READ_BYTES:ssl handshake failure:s3_pkt.c:996:
client side error:
140134052299200:error:141640B5:SSL routines:tls_construct_client_hello:no ciphers available:../ssl/statem/statem_clnt.c:800:
Can any help me out on how to establish a connection with Anonymous DH?
I create a TCP server socket that listens to connect() requests and accept() them. After accepting a client socket receives data from it. I want recv() function to block with a timeout, but it seems to be non-blocking.
I have achieved the client to be in blocking mode when receiving response from the server, but it does not seem to work the same with the server side.
Below I copy-paste the server side that I want to receive data in blocking mode:
int clientSocket = accept(_serverSocket, (struct sockaddr *)NULL, NULL);
if (clientSocket < 0)
return -1;
// set TIMEOUT option to server socket
struct timeval tv;
tv.tv_sec = 0;
tv.tv_usec = 500 * 1000;
int sockOptRet = setsockopt(clientSocket, SOL_SOCKET, SO_RCVTIMEO, (const char*)&tv, sizeof tv);
struct linger sl;
sl.l_onoff = 1; /* non-zero value enables linger option in kernel */
sl.l_linger = 0; /* timeout interval in seconds */
setsockopt(clientSocket, SOL_SOCKET, SO_LINGER, &sl, sizeof(sl));
char _rcvBuffer[sizeof(can_frame)];
int numBytesRcv = recv(clientSocket, _rcvBuffer, sizeof(can_frame), 0);
I have also tried it with MSG_WAITALL flag but it does not change anything...
Your code should clearly block, but your timeout of 0.5s doesn't do showing it justice.
If you increase the timeout to something more conspicuous such as 2s and graft the code onto, e.g., beej's tpc server template, you get something like:
/*
** server.c -- a stream socket server demo
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <sys/wait.h>
#include <signal.h>
#define PORT "3490" // the port users will be connecting to
#define BACKLOG 10 // how many pending connections queue will hold
void sigchld_handler(int s)
{
// waitpid() might overwrite errno, so we save and restore it:
int saved_errno = errno;
while(waitpid(-1, NULL, WNOHANG) > 0);
errno = saved_errno;
}
// get sockaddr, IPv4 or IPv6:
void *get_in_addr(struct sockaddr *sa)
{
if (sa->sa_family == AF_INET) {
return &(((struct sockaddr_in*)sa)->sin_addr);
}
return &(((struct sockaddr_in6*)sa)->sin6_addr);
}
int main(void)
{
int sockfd, new_fd; // listen on sock_fd, new connection on new_fd
struct addrinfo hints, *servinfo, *p;
struct sockaddr_storage their_addr; // connector's address information
socklen_t sin_size;
struct sigaction sa;
int yes=1;
char s[INET6_ADDRSTRLEN];
int rv;
memset(&hints, 0, sizeof hints);
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
hints.ai_flags = AI_PASSIVE; // use my IP
if ((rv = getaddrinfo(NULL, PORT, &hints, &servinfo)) != 0) {
fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv));
return 1;
}
// loop through all the results and bind to the first we can
for(p = servinfo; p != NULL; p = p->ai_next) {
if ((sockfd = socket(p->ai_family, p->ai_socktype,
p->ai_protocol)) == -1) {
perror("server: socket");
continue;
}
if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &yes,
sizeof(int)) == -1) {
perror("setsockopt");
exit(1);
}
if (bind(sockfd, p->ai_addr, p->ai_addrlen) == -1) {
close(sockfd);
perror("server: bind");
continue;
}
break;
}
freeaddrinfo(servinfo); // all done with this structure
if (p == NULL) {
fprintf(stderr, "server: failed to bind\n");
exit(1);
}
if (listen(sockfd, BACKLOG) == -1) {
perror("listen");
exit(1);
}
sa.sa_handler = sigchld_handler; // reap all dead processes
sigemptyset(&sa.sa_mask);
sa.sa_flags = SA_RESTART;
if (sigaction(SIGCHLD, &sa, NULL) == -1) {
perror("sigaction");
exit(1);
}
printf("server: waiting for connections...\n");
while(1) { // main accept() loop
sin_size = sizeof their_addr;
new_fd = accept(sockfd, (struct sockaddr *)&their_addr, &sin_size);
if (new_fd == -1) {
perror("accept");
continue;
}
inet_ntop(their_addr.ss_family,
get_in_addr((struct sockaddr *)&their_addr),
s, sizeof s);
printf("server: got connection from %s\n", s);
if (!fork()) { // this is the child process
close(sockfd); // child doesn't need the listener
// set TIMEOUT option to server socket
struct timeval tv;
tv.tv_sec = 2;
tv.tv_usec = 0 * 500 * 1000;
int sockOptRet = setsockopt(new_fd, SOL_SOCKET, SO_RCVTIMEO, (const char*)&tv, sizeof tv);
struct linger sl;
sl.l_onoff = 1; /* non-zero value enables linger option in kernel */
sl.l_linger = 0; /* timeout interval in seconds */
setsockopt(new_fd, SOL_SOCKET, SO_LINGER, &sl, sizeof(sl));
char can_frame[1024];
char _rcvBuffer[sizeof(can_frame)];
int numBytesRcv = recv(new_fd, _rcvBuffer, sizeof(can_frame), 0);
if (send(new_fd, "Hello, world!", 13, 0) == -1)
perror("send");
close(new_fd);
exit(0);
}
close(new_fd); // parent doesn't need this
}
return 0;
}
Now if your run this and then do:
nc localhost 3490
without typing a line to send, there should be a distinct 2-second wait
before the server gives up on you, indicating that the recv is indeed blocking.
I have the following codes..
server.c
#include <stdio.h>
#include "./../linux.h"
#include "./tcp.h"
#include <pthread.h>
static int clients = 0;
static int* memptr = NULL;
void serve(void*);
int* push(int* memptr, int nsfd) {
clients++;
if (clients == 1)
memptr = (int*)malloc(sizeof(int) * clients);
else
memptr = (int*)realloc(memptr, sizeof(int) * clients);
memptr[clients - 1] = nsfd;
return memptr;
}
int main(int argc, char** argv) {
pthread_t thread[2];
int threadCount = 0;
if (argc != 3){
printf("\nUsage: ./server port_number maximum_clients\n");
return 1;
}
static struct sockaddr_in sock, sock_client;
int len, new_sock_fd;
int sock_fd = socket(PF_INET, SOCK_STREAM, 0);
if (sock_fd == -1){
perror("socket");
exit(1);
}
sock.sin_family = PF_INET;
sock.sin_port = htons(atoi(argv[1]));
sock.sin_addr.s_addr = inet_addr("0.0.0.0");
len = sizeof(sock);
if ( bind(sock_fd, (struct sockaddr *)&sock, len) == -1){
perror("bind");
exit(1);
}
if ( listen(sock_fd, atoi(argv[2])) == -1){
perror("listen");
exit(1);
}
while(1) {
new_sock_fd = accept(sock_fd, (struct sockaddr *)&sock_client, (socklen_t *)&len);
memptr = push(memptr, new_sock_fd);
if (new_sock_fd == -1){
perror("accept");
exit(1);
}
pthread_create(&(thread[threadCount]), NULL, (void*)&serve, (void *)&new_sock_fd);
pthread_join(thread[threadCount++], NULL);
printf("threadCount = %d\n", threadCount);
sleep(1);
}
return 0;
}
void serve(void* fd){
int* new_sock_fd = (int*)fd;
Packet packet;
while(1){
bzero(&packet, sizeof(packet));
read(*new_sock_fd , &packet, sizeof(packet));
printf("%d\n", *new_sock_fd);
//printf("recipientId = %d\n", packet.recipientId);
// printf("message = %s\n", packet.data);
write(memptr[packet.recipientId - 1], packet.data, 1024);
}
pthread_exit(0);
}
and the tcp.h looks like
#ifndef __TCP_H__
# define __TCP_H__
typedef struct {
int recipientId; // this is the reciever ID
char data[1024]; // this is the main data part
}Packet;
#endif /* __TCP_H__ */
and each client.h looks like this
#include <stdio.h>
#include "./../linux.h"
#include "./tcp.h"
#include <pthread.h>
void print(void);
void scan(void);
int sock_fd;
int main(int argc, char** argv) {
if (argc != 3){
printf("\nUsage: ./client port_number server_ip\n");
return 1;
}
static struct sockaddr_in sock;
int len;
pthread_t thread1, thread2;
sock_fd = socket(PF_INET, SOCK_STREAM, 0);
if (sock_fd == -1){
perror("socket");
exit(1);
}
sock.sin_family = PF_INET;
sock.sin_port = htons(atoi(argv[1]));
sock.sin_addr.s_addr = inet_addr(argv[2]);
len = sizeof(sock);
if ( connect(sock_fd, (struct sockaddr *)&sock , len) == -1 ){
perror("connect");
exit(1);
}
pthread_create(&thread1, NULL, (void*)&print, NULL);
pthread_create(&thread2, NULL, (void*)&scan, NULL);
pthread_join(thread1, NULL);
pthread_join(thread2, NULL);
return 0;
}
void print(){
char messege[1024];
while(1){
if (read(sock_fd, messege, 1024) == -1){
perror("read");
return;
}
printf("messege = %s\n", messege);
}
pthread_exit(0);
}
void scan(void){
Packet packet;
while(1){
printf("Enter the reciver ID: ");
scanf("%d", &packet.recipientId);
printf("Enter the data: ");
scanf("%s", packet.data);
if ( write(sock_fd, &packet, sizeof(packet)) == -1) {
perror("read");
return;
}
}
pthread_exit(0);
}
Now the problems are
when I am running the server & the in 2 terminals, 2 clients after each client is accepted threadCount should be printed at the server end but it is not printing. It means the execution stops/skips after the first pthread_join but WHY ??
After connecting two threads, when I sent the data from 1st client to the 1st client itself, it works but not from the 1st client to the 2nd client..rather it is sending to the server terminal window. WHY ??
When sent from the second client nothing works ( sending itself or client 1)..WHY??
Please help..And thanks for patiently reading all the codes above.
TCP is a byte stream protocol, not a message protocol. You are calling TCP functions and expecting them to send or receive messages. They don't. If you want to send or receive messages, you have to implement a message protocol, write functions that send and receive messages, and then call those functions.
if (read(sock_fd, messege, 1024) == -1){
perror("read");
return;
}
printf("messege = %s\n", messege);
This call to printf is a disaster. The %s format specifier is for C-style strings, not arbitrary chunks of bytes received from a byte stream. For the most obvious way to see how bad this is, consider this --- how should printf decide how many bytes to print? You threw away the value read returned after you compared it to -1, so you have no idea how many bytes you received.
I'm sure there are other issues with your code, but the fact that the fundamental design is broken makes it not worth fixing those issues. Instead, design a message protocol and implement that.