I'm developping an application which will run on a bosch device - XDK - http://xdk.bosch-connectivity.com/.
At this moment, I have a task which implements an http client and sends POST requests to a server. However, the main purpose of my application is to be able to move between areas with network coverage/no coverage. This means that I'm constantly suspending/re-starting the task that implements the http client.
So I'm having problem with the http client in the following scenario: I start the application in a region with coverage, then I move to a region with no coverage and finally, go back again to a region with coverage. That's here I'm getting problems. From that moment, I can't connect anymore with the http client.
I'll post here pieces of code of my application so that you can suggest me some alterations to solve the problem.
All the functions such as HttpClient_initRequest, HttpMsg_setReqUrl, Msg_prependPartFactory, ..., belong to the API provided for the XDK.
void appInitSystem(xTimerHandle xTimer) {
(void) (xTimer);
return_t retValue = FAILURE;
retcode_t wlanRet = RC_PLATFORM_ERROR;
wlanRet = wlan_init();
if (wlanRet != RC_OK){
printf("Network init/connection failed %i \r\n", wlanRet);
assert(0);
}
wlanRet = PAL_initialize();
if (wlanRet != RC_OK){
printf("PAL and network initialize %i \r\n", wlanRet);
assert(0);
}
PAL_socketMonitorInit();
/* start http client */
wlanRet = HttpClient_initialize();
if (wlanRet != RC_OK){
printf("Failed to initialize http client\r\n ");
assert(0);
}
if (RC_OK != PAL_getIpaddress((uint8_t*) "52.58.121.5", &destAddr))
return;
retValue = createTasks();
if (retValue == FAILURE)
assert(0);
}
retcode_t wlan_init(void) {
WLI_connectStatus_t retconnection;
NCI_ipSettings_t myIpSettings;
char ipAddress[PAL_IP_ADDRESS_SIZE] = { 0 };
Ip_Address_T* IpaddressHex = Ip_getMyIpAddr();
WLI_connectSSID_t connectSSID;
WLI_connectPassPhrase_t connectPassPhrase;
NCI_return_t ReturnValue = NCI_FAILURE;
int32_t Result = INT32_C(-1);
if (WLI_SUCCESS != WLI_init())
return (RC_PLATFORM_ERROR);
connectSSID = (WLI_connectSSID_t) WLAN_CONNECT_WPA_SSID;
connectPassPhrase = (WLI_connectPassPhrase_t) WLAN_CONNECT_WPA_PASS;
/*DHCP */
ReturnValue = NCI_setIpDhcp(NULL);
if (ReturnValue != NCI_SUCCESS){
printf("Error in setting IP to DHCP\n\r");
return (RC_PLATFORM_ERROR);
}
if (WLI_SUCCESS == WLI_connectWPA(connectSSID, connectPassPhrase, NULL){
ReturnValue = NCI_getIpSettings(&myIpSettings);
if (NCI_SUCCESS == ReturnValue){
*IpaddressHex = Basics_htonl(myIpSettings.ipV4);
Result = Ip_convertAddrToString(IpaddressHex, ipAddress);
if (Result < 0){
printf("Couldn't convert the IP address to string format \r\n ");
return (RC_PLATFORM_ERROR);
}
printf("Connected to WPA network successfully \r\n ");
printf(" Ip address of the device %s \r\n ", ipAddress);
return (RC_OK);
}
else{
printf("Error in getting IP settings\n\r");
return (RC_PLATFORM_ERROR);
}
}
else
return (RC_PLATFORM_ERROR);
return RC_OK;
}
/* Task which calls the nttp client */
void dataOffload(void* handle) {
(void) handle;
for (;;){
....
http_connServer(NULL);
...
vTaskDelay(1000/portTICK_RATE_MS);
}
}
void http_connServer(void * pvParameters){
retcode_t rc = RC_OK;
Msg_T* msg_ptr;
Ip_Port_T destPort = (Ip_Port_T) DEST_PORT_NUMBER;
static Callable_T SentCallable;
char const *url_ptr = "/";
Callable_T * Callable_pointer;
Callable_pointer = Callable_assign(&SentCallable, http_callbackOnSent);
if (Callable_pointer == NULL)
return;
rc = HttpClient_initRequest(&destAddr, Ip_convertIntToPort(destPort), &msg_ptr);
if (rc != RC_OK || msg_ptr == NULL)
return;
rc = Msg_prependPartFactory( msg_ptr, &http_setContent);
if (rc != RC_OK)
return;
rc = HttpMsg_setReqUrl(msg_ptr, url_ptr);
if (rc != RC_OK)
return;
HttpMsg_setReqMethod(msg_ptr, Http_Method_Post);
rc = HttpClient_pushRequest(msg_ptr, &SentCallable,
http_clientResponseCallback);
if (rc != RC_OK){
printf("Failed HttpClient_pushRequest \r\n ");
return;
}
}
Related
so i am trying to implement a TCP server-client(s) using server ip and port. Connection between the two was established, with the use of threads.
Now i'm expecting the program to: for everytime a client joins or leave, if there are other clients present, then it will print "Client has joined/left the server" on these other clients screen. However if it is the only client present, it won't say the join or leave stuff and will proceed with asking user an input of what does the client wants to do.(user input is what the client has typed after this arrow ">")
What it is actually doing: When the first client has successfully joined the server, the command line remains empty, the ">" does not appear and even if you can type, no input is recorded by the client. As you connect a second client, that's when the arrow appears on the first client only and you can start inputting.
I would like to know which part i should edit to make my client when alone to start taking input without needing another client to join before doing so + When there are multiple clients and a client joins/leave, on the other clients' screen is printed "Client has joined/left the server"
Server code
void client_queuing(client_thr *cl){
pthread_mutex_lock(&cli_mutex);
for(int i=0; i < MAXLINE; ++i){
if(!cli[i]){
cli[i] = cl;
break;
}
}
pthread_mutex_unlock(&cli_mutex);
}
void client_removal(int uid){
pthread_mutex_lock(&cli_mutex);
for(int i=0; i < MAXLINE; ++i){
if(cli[i]){
if(cli[i]->uid == uid){
cli[i] = NULL;
break;
}
}
}
pthread_mutex_unlock(&cli_mutex);
}
void convey_msg(char *st, int uid){
pthread_mutex_lock(&cli_mutex);
for(int i=0; i<MAXLINE; ++i){
if(cli[i]){
if(cli[i]->uid != uid){
if(write(cli[i]->sockfd, st, strlen(st)) < 0){
perror("ERROR: Failure to write to descriptor");
break;
}
}
}
}
pthread_mutex_unlock(&cli_mutex);
}
void *man_cli(void *arg){
char buffer_o[SIZEOF_BUFFER];
char nickname[20];
int leave_flag = 0;
num_client++;
client_thr *clice = (client_thr *)arg;
// nickname
if(recv(clice->sockfd, nickname, 20, 0) <= 0 || strlen(nickname) >= 19){
printf("Name not Entered.\n");
leave_flag = 1;
}
else{
strcpy(cli->nickname, nickname);
sprintf(buffer_o, "A new user %s has joined SNC!\n", cli->nickname);
printf("%s", buffer_o);
convey_msg(buffer_o, clice->uid);
}
bzero(buffer_o, SIZEOF_BUFFER);
while(1){
if (leave_flag) {
break;
}
int receive = recv(clice->sockfd, buffer_o, SIZEOF_BUFFER, 0);
if (receive > 0){
if(strlen(buffer_o) > 0){
convey_msg(buffer_o, clice->uid);
array_trimming(buffer_o, strlen(buffer_o));
printf("%s -> %s\n", buffer_o, clice->nickname);
//printf("%s\n", buffer_o);
}
}
else if (receive == 0 || strcmp(buffer_o, "quit") == 0){
sprintf(buffer_o, "Server: %s has stopped chatting.\n", clice->nickname);
printf("%s", buffer_o);
convey_msg(buffer_o, clice->uid);
//trial
//strcpy(buffer_o, clice->nickname);
send(clice->sockfd, buffer_o, strlen(buffer_o)+1,0);
leave_flag = 1;
}
/* else {
printf("Error is -1\n");
leave_flag = 1;
} */
bzero(buffer_o, SIZEOF_BUFFER);
}
/* Delete client from queue and yield thread */
close(clice->sockfd);
client_removal(clice->uid);
free(clice);
num_client--;
pthread_detach(pthread_self());
return NULL;
}
client code
void handle_message_convey() {
char message[LENGTH] = {};
char buff[LENGTH + 20] = {};
while(1) {
flush_stdout();
fgets(message, LENGTH, stdin);
array_trimming(message, LENGTH);
if (strcmp(message, "quit") == 0) {
break;
}
else {
sprintf(buff, "%s: %s\n", nickname, message);
send(sockfd, buffer, strlen(buff), 0);
}
bzero(message, LENGTH);
bzero(buffer, LENGTH + 20);
}
quit_with_catch_ctrl_c(2);
}
void handle_message_recv() {
char message[LENGTH] = {};
while (1) {
int message_rcv = recv(sockfd, message, LEN, 0);
if (message_rcv > 0) {
printf("%s", message);
flush_stdout();
}
else if (message_rcv == 0) {
break;
}
else {
// nothing happens = -1
}
memset(message, 0, sizeof(message));
}
}
int main(){
recv(sock_fd, buffer_o, sizeof(buffer_o), 0);
//printf("%s \n", buffer_o);
pthread_t message_sending_thr;
if(pthread_create(&message_sending_thr, NULL, (void* ) handle_message_convey, NULL) != 0) {
printf("Error with pthread:");
}
//printf("Hello, Welcome!");
pthread_t message_del_thr;
if(pthread_create(&message_del_thr, NULL, (void *)handle_message_recv, NULL) != 0){
printf("Error with pthread");
}
}
I'm trying to create a chatroom. I have a server that takes commands and does things with them and I have client that sends them. Im using poll to monitor multiple clients. Whenever my client sends a command with the arguments it reads that line and gets some characters from the following line in client.
client(relevant code):
char *data = "REGISTER Johndoe pass1ds3";
send(sockfd,data, strlen(data), 0);
char *data3= "LOGIN Johndoe pass1ds3";
send(sockfd,data3, strlen(data3), 0);
//The server would get "REGISTER Johndoe pass1ds3LOGIN" instead of "REGISTER Johndoe pass1ds3".
server(relevant par):
for (int i = 1; i < (numfds + 1); i++){
if(pollfds[i].revents & POLLRDNORM){
if (readCmd(&pollfds[i], pollfds[i].fd, users,cmdBuf, 32) == -1)
printf("Connection closed\n");
else if(readCmd(&pollfds[i], pollfds[i].fd, users ,cmdBuf, 32) == -2)
printf("Error with recv");
}
}
readCmd(the command that reads from client):
int readCmd(struct pollfd * pollInfo, int sockfd, struct user *users,char* buf, int bufSize){
int num = recv(sockfd , buf, bufSize, 0);
if( num == -1)
return -2;
else if (num == 0 || (num < 0 && errno == ECONNRESET)){
// printf("Nothing to read\n");
close(sockfd);
return -1;
}
else{
printf("recieved %d bytes\n", num);
buf[num] = '\0';
char tokenList[5][30];
char* context = NULL;
char* token = strtok_r(buf, " ", &context);
// Parse command and arguments
int ite = 0;
while (token != NULL) {
strcpy(tokenList[ite], token);
ite++;
token = strtok_r(NULL, " ", &context);
}
if(strcmp(tokenList[0], "REGISTER") == 0){
registerAcc(tokenList[1], tokenList[2]);
}
else if (strcmp(tokenList[0], "LOGIN") == 0){
login(tokenList[1], tokenList[2], users);
}
}
return 0;
}
I just started learning about HTTP2.0 protocol and the nghttp2 library. I started with the examples from the project (libevent-client.c (https://nghttp2.org/documentation/tutorial-client.html) and libevent-server.c(https://nghttp2.org/documentation/tutorial-server.html)).
I am trying to find a function in nghttp2 library that gives me the number of concurrent streams supported by the server in the client.
static int send_server_connection_header(http2_session_data *session_data) {
nghttp2_settings_entry iv[1] = {
{NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS, 100}};
int rv;
rv = nghttp2_submit_settings(session_data->session, NGHTTP2_FLAG_NONE, iv,
ARRLEN(iv));
if (rv != 0) {
warnx("Fatal error: %s", nghttp2_strerror(rv));
return -1;
}
return 0;
}
static int session_send(http2_session_data *session_data) {
int rv;
rv = nghttp2_session_send(session_data->session);
if (rv != 0) {
warnx("Fatal error: %s", nghttp2_strerror(rv));
return -1;
}
return 0;
}
In the eventcb callback server send settings, but where is this message
received in the client?
if (send_server_connection_header(session_data) != 0 ||
session_send(session_data) != 0) {
delete_http2_session_data(session_data);
return;
}
How can I see this setting in the client?
I'am curently building a C Tasker, the goal of the program is to connect to a Main Server via Websockets and keep the connection Alive(Client Watchdog) as long as it is possible.
In the mean time the Tasker should be able to receive Jsons from clients (Server Behaviour), process them accordingly and answer.
To perfom this i use GLib's multi threading methods and the Libwebsockets library for the network part.
The C Client/Server Tasker is working well so the next step should be : when the connection is lost with the Main Server to try to reconnect "forever" until the Main Server is up, or to Fallback on another Main Server.
The problem here is that when i cut the connection with the server the watchdog thread seems to ignore the reconnection. As the thread is completely isolated from the libwesockets callbacks.
Here are the code snippets :
Call of Tasker Client in Tasker Server init
int janus_websockets_init(janus_transport_callbacks *callback, const char *config_path) {
if(g_atomic_int_get(&stopping)) {
return -1;
}
if(callback == NULL || config_path == NULL)
return -1;
gateway = callback;
Client_start()
Tasker Server configuration
struct lws_context_creation_info info;
memset(&info, 0, sizeof info);
info.port = wsport;
info.iface = ip ? ip : interface;
info.protocols = wss_protocols;
info.extensions = NULL;
info.ssl_cert_filepath = NULL;
info.ssl_private_key_filepath = NULL;
info.gid = -1;
info.uid = -1;
info.options = 0;
/* Create the WebSocket context */
wss = lws_create_context(&info);
if(wss == NULL) {
ZETA_LOG(LOG_FATAL, "Error initializing libwebsockets...\n");
} else {
ZETA_LOG(LOG_INFO, "WebSockets server started (port %d)...\n", wspor\
t);
}
Tasker Client Configuration
int
Client_start()
{
//* register the signal SIGINT handler */
struct lws_context_creation_info info;
memset(&info, 0, sizeof info);
info.port = CONTEXT_PORT_NO_LISTEN;
info.iface = NULL;
info.protocols = wss_protocols;
info.ssl_cert_filepath = NULL;
info.ssl_private_key_filepath = NULL;
info.extensions = lws_get_internal_extensions();
info.gid = -1;
info.uid = -1;
info.options = 0;
protocol.name = "janus-protocol";
protocol.callback = &ws_client_service_callback;
protocol.per_session_data_size = sizeof(struct session_data);
protocol.rx_buffer_size = 0;
protocol.id = 0;
protocol.user = NULL;
context = lws_create_context(&info);
Tasker Client Watchdog Thread Call
if (context == NULL) {
printf(KRED"[Main Service] context is NULL.\n"RESET);
return -1;
}
wsz = lws_client_connect(context, "xxx.xxx.xxx.xxx",5000, 0,
"/", "xxx.xxx.xxx.xxx:5000", NULL,
protocol.name, -1);
if (wsz == NULL) {
printf(KRED"[Main] wsi create error.\n"RESET);
return -1;
}
reco = false;
printf(KGRN"[Main] wsi create success.\n"RESET);
printf(KRED"[Main Service] %d\n", ConnOk, RESET);
keepAlive = g_thread_try_new("KeepAliveLoop", keep_alive_routine, context, NULL);
while(!dead)
lws_service(context, 50);
lws_context_destroy(context);
return 0;
}
Finnaly The Tasker Client Thread routine Loop and Thread Loop Execution code
static void keep_alive_loop()
{
json_t *hb = NULL;
char *toto = NULL;
if (reco == true)
{
wsz = lws_client_connect(context, "xxx.xxx.xxx.xxx",5000, 0,
"/", "xxx.xxx.xxx.xxx:5000", NULL,
protocol.name, -1);
printf(KRED"[Main Service] UNDER LOOOOOOPING .\n"RESET);
reco = false;
return;
}
hb = json_object();
json_object_set_new(hb, "zetapush", json_string("keepalive"));
json_object_set_new(hb, "timeout", json_integer(8000));
toto = json_dumps(hb, 0);
websocket_client_keep_alive_write_back(hb);
lws_callback_on_writable(wsz);
}
static void *keep_alive_routine(void *data)
{
printf(KBRN"[pthread_routine] WATCHDOG READY AND ANGRY .\n"RESET);
g_timeout_add_seconds(8, keep_alive_loop, NULL);
alive_loop = g_main_loop_new(NULL, 0);
g_main_loop_run(alive_loop);
}
If any further precision is needed let me know, i can also upload to github for better reading, any help or hint would be much appreciated :).
I want make a non-blocking OpenSSL connection
On this connection - if no data available for read, then entire program execution flow make stop on SSL_read(). I want so that if no data available for read it give me the returns values like WANT_READ and i know no more data available.
char *sslRead (connection *c)
{
const int readSize = 1024;
char *rc = NULL;
int r;
int received, count = 0;
int ReallocSize = 0;
char buffer[1024];
if (c)
{
while (1)
{
if (!rc)
{
rc = malloc (readSize + 1);
if (rc == NULL)
printf("the major error have happen. leave program\n");
}
else
{
ReallocSize = (count + 1) * (readSize + 1);
rc = realloc (rc, ReallocSize);
}
// if i have no data available for read after reading data,
// this call will not return anything and wait for more data
// i want change this non blocking connections
received = SSL_read (c->sslHandle, buffer, readSize);
buffer[received] = '\0';
if (received <= 0)
{
printf(" received equal to or less than 0\n");
switch (SSL_get_error(c->sslHandle, r))
{
case SSL_ERROR_NONE:
printf("SSL_ERROR_NONE\n");
break;
case SSL_ERROR_ZERO_RETURN:
printf("SSL_ERROR_ZERO_RETURN\n");
break;
case SSL_ERROR_WANT_READ:
printf("SSL_ERROR_WANT_READ\n");
break;
default:
printf("error happens %i\n", r);
}
break;
}
count++;
}
}
return rc;
}
here is how i make connection
connection *sslConnect (void)
{
connection *c;
c = malloc (sizeof (connection));
c->sslHandle = NULL;
c->sslContext = NULL;
c->socket = tcpConnect ();
if (c->socket)
{
// Register the error strings for libcrypto & libssl
SSL_load_error_strings ();
// Register the available ciphers and digests
SSL_library_init ();
// New context saying we are a client, and using SSL 2 or 3
c->sslContext = SSL_CTX_new (SSLv23_client_method ());
if (c->sslContext == NULL)
ERR_print_errors_fp (stderr);
// Create an SSL struct for the connection
c->sslHandle = SSL_new (c->sslContext);
if (c->sslHandle == NULL)
ERR_print_errors_fp (stderr);
// Connect the SSL struct to our connection
if (!SSL_set_fd (c->sslHandle, c->socket))
ERR_print_errors_fp (stderr);
// Initiate SSL handshake
if (SSL_connect (c->sslHandle) != 1)
ERR_print_errors_fp (stderr);
}
else
{
perror ("Connect failed");
}
return c;
}
thanks you very much.
Creating a non-blocking socket is a pre-requisite to a non-blocking connect...
The following steps summarize: (see complete description in site linked below)
1) Call the fcntl() API to retrieve the socket descriptor's current flag settings into a local variable.
2) In that local variable, set the O_NONBLOCK (non-blocking) flag on. (being careful not to tamper with the other flags)
3) Call the fcntl() API to set the flags for the descriptor to the value in our local variable.
( read more on non-blocking sockets techniques here )
Assuming an existing socket, the following implements the steps outlined above:
BOOL SetSocketBlockingEnabled(SOCKET fd, BOOL blocking)
{
if (fd < 0) return FALSE;
#ifdef WIN32
unsigned long mode = blocking ? 0 : 1;
return (ioctlsocket(fd, FIONBIO, &mode) == 0) ? TRUE : FALSE;
#else
int flags = fcntl(fd, F_GETFL, 0);
if (flags < 0) return false;
flags = blocking ? (flags&~O_NONBLOCK) : (flags|O_NONBLOCK);
return (fcntl(fd, F_SETFL, flags) == 0) ? TRUE : FALSE;
#endif
}
Once you have a non-blocking socket, then see this post explaining how to do a non-blocking connect