Enquiry with RSSI stuck with CSR4.0 bluetooth dongle - c++

I am using bluez enquiry mode to scan bluetooth client with RSSI.I am using c code enquiry_with _rssi.I am using CSR4.0 bluetooth dongle and not able to scan.
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/poll.h>
#include <sys/ioctl.h>
#include <bluetooth/bluetooth.h>
#include <bluetooth/hci.h>
#include <bluetooth/hci_lib.h>
static void print_result(const bdaddr_t *bdaddr, char has_rssi, int rssi,int sock)
{
char addr[18];
char name[248] = { 0 };
ba2str(bdaddr, addr);
memset(name, 0, sizeof(name));
if (hci_read_remote_name(sock, bdaddr, sizeof(name), name, 0) < 0)
strcpy(name, "[unknown]");
printf("%17s \t", addr);
printf("%s \t", name);
if(has_rssi)
printf(" RSSI:%d", rssi);
else
printf(" RSSI:n/a");
printf("\n");
fflush(NULL);
}
static void scanner_start()
{
int dev_id, sock = 0;
struct hci_filter flt;
inquiry_cp cp;
unsigned char buf[HCI_MAX_EVENT_SIZE], *ptr;
hci_event_hdr *hdr;
char canceled = 0;
inquiry_info_with_rssi *info_rssi;
inquiry_info *info;
int results, i, len;
struct pollfd p;
dev_id = hci_get_route(NULL);
sock = hci_open_dev( dev_id );
if (dev_id < 0 || sock < 0) {
perror("Can't open socket");
return;
}
hci_filter_clear(&flt);
hci_filter_set_ptype(HCI_EVENT_PKT, &flt);
hci_filter_set_event(EVT_INQUIRY_RESULT, &flt);
hci_filter_set_event(EVT_INQUIRY_RESULT_WITH_RSSI, &flt);
hci_filter_set_event(EVT_INQUIRY_COMPLETE, &flt);
if (setsockopt(sock, SOL_HCI, HCI_FILTER, &flt, sizeof(flt)) < 0) {
perror("Can't set HCI filter");
return;
}
if (hci_send_cmd(sock, OGF_HOST_CTL, OCF_WRITE_INQUIRY_MODE,
WRITE_INQUIRY_MODE_RP_SIZE, &cp) < 0) {
perror("Can't set inquiry mode");
return;
}
memset (&cp, 0, sizeof(cp));
cp.lap[2] = 0x9e;
cp.lap[1] = 0x8b;
cp.lap[0] = 0x33;
cp.num_rsp = 0;
cp.length = 0x30;
printf("Starting inquiry with RSSI...\n");
if (hci_send_cmd (sock, OGF_LINK_CTL, OCF_INQUIRY, INQUIRY_CP_SIZE,&cp) < 0) {
perror("Can't start inquiry");
return;
}
p.fd = sock;
p.events = POLLIN | POLLERR | POLLHUP;
while(!canceled) {
p.revents = 0;
/* poll the BT device for an event */
if (poll(&p, 1, -1) > 0) {
len = read(sock, buf, sizeof(buf));
if (len < 0)
continue;
else if (len == 0)
break;
printf("len= %d \n",len);
hdr = (void *) (buf + 1);
ptr = buf + (1 + HCI_EVENT_HDR_SIZE);
results = ptr[0];
printf("results %d \n",results);
switch (hdr->evt)
{
case EVT_INQUIRY_RESULT:
for (i = 0; i < results; i++) {
info = (void *)ptr + (sizeof(*info) * i) + 1;
print_result(&info->bdaddr, 0, 0,sock);
}
break;
case EVT_INQUIRY_RESULT_WITH_RSSI:
for (i = 0; i < results; i++) {
info_rssi = (void *)ptr + (sizeof(*info_rssi) * i) + 1;
print_result(&info_rssi->bdaddr, 1, info_rssi->rssi,sock);
}
break;
case EVT_INQUIRY_COMPLETE:
canceled = 1;
break;
}
}
}
close(sock);
}
int main(int argc, char **argv)
{
scanner_start();
return 0;
}
[lsusb,i have two bluetooth adaptor,down hci0 and up hci1][1]
compile above code but not able to search any client
when i execute the command sudo hciconfig hci1 inqmode 1,then it scan one client and stucks,not able to scan other device
i hope CSR4.0 support Enquiry with RSSI,and features of CSR4.0,you can see in 4 and 5 image.
So,where is the problem,why it stucks after scan one devices.

Related

C++ non-blocking send/recv work only on one side(client or server)

I'm implementing a server in C++ with non-blocking sockets.
Since I want to send messages between the client & server, I wrote 2 wrappers around send/recv syscalls. Mainly, I want to prepend 4Bytes (message length) to every message, so that the receiver knows how long to execute recv.
Moreover I have a client/server programs that each start a socket and listen on localhost.
Then the client sends a random message, which the server receives.
When I try,however, to send from the server to the client, both programs halt.
I have tested the wrappers many times and they read/deliver data, but whenever I try to receive on a previously sending connection, then comes the problem.
I know that there is a memory leak in the secure_recv but I need it to pass some custom tests, which are not very well written.
The issue lies in the select, which returns a positive number, but then I never go inside the if (FD_ISSET(fd, &readset)) statement.
What am I doing wrong and how can we fix it ? Thanks a lot !
EDIT
My problem was that the sockets were blocking(busy working) at the select function. I updated the code so that there is no select in the secure_* functions. It's a much better way to first check if the socket is available for send/recv on a client/server thread level via select and then calling the secure_* functions. Question is answered for now.
client.cpp
// Client side C/C++ program to demonstrate Socket programming
#include <stdio.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <string.h>
#include "util.h"
#define PORT 8080
int main(int argc, char const *argv[])
{
int sock = 0, valread;
struct sockaddr_in serv_addr;
if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0)
{
printf("\n Socket creation error \n");
return -1;
}
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(PORT);
// Convert IPv4 and IPv6 addresses from text to binary form
if (inet_pton(AF_INET, "127.0.0.1", &serv_addr.sin_addr) <= 0)
{
printf("\nInvalid address/ Address not supported \n");
return -1;
}
if (connect(sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0)
{
printf("\nConnection Failed \n");
return -1;
}
int numbytes;
size_t size = 0;
std::unique_ptr<char[]> buf = get_rand_data(size);
if ((numbytes = secure_send(sock, buf.get(), size, 0)) == -1)
{
std::cout << std::strerror(errno) << "\n";
exit(1);
}
std::cout << "Client sent : " << numbytes << "\n";
int64_t bytecount = -1;
while (1)
{
std::unique_ptr<char[]> buffer;
if ((bytecount = secure_recv(sock, buffer, 0)) <= 0)
{
if (bytecount == 0)
{
break;
}
}
std::cout << bytecount << "\n";
}
std::cout << "Client received : " << bytecount << "\n";
close(sock);
return 0;
}
server.cpp
// Server side C/C++ program to demonstrate Socket programming
#include <unistd.h>
#include <stdio.h>
#include <sys/socket.h>
#include <stdlib.h>
#include <netinet/in.h>
#include <string.h>
#include "util.h"
#define PORT 8080
int main(int argc, char const *argv[])
{
int server_fd, new_socket, valread;
struct sockaddr_in address;
int opt = 1;
int addrlen = sizeof(address);
// Creating socket file descriptor
if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == 0)
{
perror("socket failed");
exit(EXIT_FAILURE);
}
// Forcefully attaching socket to the port 8080
if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT,
&opt, sizeof(opt)))
{
perror("setsockopt");
exit(EXIT_FAILURE);
}
address.sin_family = AF_INET;
address.sin_addr.s_addr = INADDR_ANY;
address.sin_port = htons( PORT );
// Forcefully attaching socket to the port 8080
if (bind(server_fd, (struct sockaddr *)&address,
sizeof(address))<0)
{
perror("bind failed");
exit(EXIT_FAILURE);
}
if (listen(server_fd, 3) < 0)
{
perror("listen");
exit(EXIT_FAILURE);
}
if ((new_socket = accept(server_fd, (struct sockaddr *)&address,
(socklen_t*)&addrlen))<0)
{
perror("accept");
exit(EXIT_FAILURE);
}
// set the socket to non-blocking mode
fcntl(new_socket, F_SETFL, O_NONBLOCK);
int64_t bytecount = -1;
while (1) {
std::unique_ptr<char[]> buffer;
if ((bytecount = secure_recv(new_socket, buffer, 0)) <= 0) {
if (bytecount == 0) {
break;
}
}
std::cout << bytecount << "\n";
}
int numbytes;
size_t size = 0;
std::unique_ptr<char[]> buf = get_rand_data(size);
if ((numbytes = secure_send(new_socket, buf.get(), size, 0)) == -1)
{
std::cout << std::strerror(errno) << "\n";
exit(1);
}
std::cout << "Client sent : " << numbytes << "\n";
close(new_socket);
return 0;
}
util.h
#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 <arpa/inet.h>
#include <time.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/wait.h>
#include <signal.h>
#include <cstring>
#include <iostream>
#include <thread>
#include <vector>
#include <mutex>
#include <condition_variable>
#include <algorithm>
#include <memory>
#include <poll.h>
#include <iomanip>
/**
* It takes as arguments one char[] array of 4 or bigger size and an integer.
* It converts the integer into a byte array.
*/
void convertIntToByteArray(char *dst, int sz)
{
auto tmp = dst;
tmp[0] = (sz >> 24) & 0xFF;
tmp[1] = (sz >> 16) & 0xFF;
tmp[2] = (sz >> 8) & 0xFF;
tmp[3] = sz & 0xFF;
}
/**
* It takes as an argument a ptr to an array of size 4 or bigger and
* converts the char array into an integer.
*/
int convertByteArrayToInt(char *b)
{
return (b[0] << 24) + ((b[1] & 0xFF) << 16) + ((b[2] & 0xFF) << 8) + (b[3] & 0xFF);
}
/**
* It constructs the message to be sent.
* It takes as arguments a destination char ptr, the payload (data to be sent)
* and the payload size.
* It returns the expected message format at dst ptr;
*
* |<---msg size (4 bytes)--->|<---payload (msg size bytes)--->|
*
*
*/
void construct_message(char *dst, char *payload, size_t payload_size)
{
convertIntToByteArray(dst, payload_size);
memcpy(dst + 4, payload, payload_size);
}
/**
* It returns the actual size of msg.
* Not that msg might not contain all payload data.
* The function expects at least that the msg contains the first 4 bytes that
* indicate the actual size of the payload.
*/
int get_payload_size(char *msg, size_t bytes)
{
// TODO:
return convertByteArrayToInt(msg);
}
/**
* Sends to the connection defined by the fd, a message with a payload (data) of size len bytes.
* The fd should be non-blocking socket.
*/
/**
* Receives a message from the fd (non-blocking) and stores it in buf.
*/
int secure_recv(int fd, std::unique_ptr<char[]> &buf)
{
// TODO:
int valread = 0;
int len = 0;
int _len = 4;
bool once_received = false;
std::vector<char> ptr(4);
while (_len > 0)
{
int _valread = recv(fd, ptr.data() + valread, _len, MSG_DONTWAIT);
if (_valread == 0)
{
break;
}
if (_valread > 0)
{
_len -= _valread;
valread += _valread;
}
if (!once_received && valread == 4)
{
once_received = true;
len = convertByteArrayToInt(ptr.data());
_len = len;
ptr = std::vector<char>(len);
valread = 0;
}
}
buf = std::make_unique<char[]>(len);
memcpy(buf.get(), ptr.data(), len);
return len;
}
/**
* Sends to the connection defined by the fd, a message with a payload (data) of size len bytes.
* The fd should be non-blocking socket.
*/
int secure_send(int fd, char *data, size_t len)
{
// TODO:
char ptr[len + 4];
int valsent = 0;
int _len = 4;
bool once_sent = false;
construct_message(ptr, data, len);
while (_len > 0)
{
int _valsent = send(fd, ptr + valsent, _len, MSG_DONTWAIT);
if (_valsent == 0)
{
break;
}
if (_valsent > 0)
{
_len -= _valsent;
valsent += _valsent;
}
if (!once_sent && valsent == 4)
{
once_sent = true;
_len = len;
}
}
return len;
}
Compilation via
g++ -O3 -std=c++17 -Wall -g -I../ client.cpp -o client -lpthread
Let's start with the write loop:
while (1)
{
// std::cerr << "first iteration send\n";
FD_ZERO(&writeset);
FD_SET(fd, &writeset);
if (select(fd + 1, NULL, &writeset, NULL, NULL) > 0)
{
if (FD_ISSET(fd, &writeset))
{
valsent = send(fd, ptr + valsent, _len, 0);
Oops. This loses valsent, which tracks how many bytes you've sent so far. So on your third loop, ptr + valsent will only add the number of bytes received the second time. You need to track the total number of bytes sent so far somewhere.
if (valsent <= 0)
{
break;
}
_len -= valsent;
And what if _len becomes zero? You'll still call select and even send. You probably want that while (1) to be while (_len > 0).
}
}
}
return len;
Now, onto the read loop:
if (select(fd + 1, &readset, NULL, NULL, NULL) > 0)
{
if (FD_ISSET(fd, &readset))
{
if (first_iteration)
{
recv(fd, ptr, 4, 0);
You ignore the return value of recv here. What if it's not 4?
len = convertByteArrayToInt(ptr);
buf = std::make_unique<char[]>(len);
_len = len;
first_iteration = false;
}
valread = recv(fd, buf.get() + valread, _len, 0);
if (valread <= 0)
{
break;
}
_len -= valread;
You don't leave the loop if _len is zero. You'll call select again, waiting for data that may never come.
}
}

icmp dereferencing pointer to incomplete type 'struct icmp'

I got an error:
dereferencing pointer to incomplete type 'struct ip'
138| u_int8_t icmp_Type = icmp_package->icmp_type;
I've made some research, found some similar topics on this, but nothing helped. The problem probably is with icmp.
The program works like traceroute in a Linux terminal.
None of these seem to work to fix it:
adding -D_GNU_SOURCE to gcc command
adding __USE_BSD
Does anyone know how to solve it?
Compiling on Linux with gcc -std=c17
#include <netinet/ip.h>
#include <netinet/ip_icmp.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <sys/time.h>
#include <unistd.h>
int receive_from(int sockfd, char recipient[20], int PID, int TTL, char response[20]);
void print_as_bytes (unsigned char* buff, ssize_t length)
{
for (ssize_t i = 0; i < length; i++, buff++)
printf ("%.2x ", *buff);
}
void print_row(int RCV_NUM, int avg, int TTL, char responses[3][20])
{
if(TTL < 10)
printf(" ");
printf("%d", TTL);
if(RCV_NUM == 0)
{
printf("*\n");
} else {
printf(" %s", responses[0]);
if(strcmp(responses[0], responses[1]) != 0)
printf(" %s", responses[1]);
if(strcmp(responses[0], responses[2]) != 0 && strcmp(responses[1], responses[2]) != 0)
printf(" %s", responses[2]);
if(RCV_NUM < 3)
printf(" ???\n");
else
printf(" %d ms", avg);
}
}
int receive(int sockfd, char recipient[20], int PID, int TTL)
{
int DEST_REACHED = 0;
char responses[3][20] = {"", "", ""};
struct timeval time;
gettimeofday(&time, NULL);
long long start = ((long long)time.tv_sec * 1000) + (time.tv_usec / 1000);
fd_set descriptors;
FD_ZERO(&descriptors);
FD_SET(sockfd, &descriptors);
struct timeval tv;
tv.tv_sec = 1;
tv.tv_usec = 0;
int time_passed = 0;
int which = 0;
while(which < 3)
{
int ready = select (sockfd+1, &descriptors, NULL, NULL, &tv);
if(ready < 0)
{
fprintf(stderr, "traceroute: select error: %s\n", strerror(errno));
which++;
}
if(ready > 0)
{
gettimeofday(&time, NULL);
long long timeNow = ((long long)time.tv_sec * 1000) + (time.tv_usec / 1000);
time_passed += timeNow - start;
int result = receive_from(sockfd, recipient, PID, TTL, responses[which]);
if(result == -1)
{
fprintf(stderr, "traceroute: Package missed\n");
which++;
continue;
}
if(result == 1)
{
DEST_REACHED = 1;
}
which++;
if(which == 3)
{ break; }
}
if(ready == 0)
{
which++;
}
}
int avg;
int RCV_NUM = 3;
if(which < 3)
{
RCV_NUM = which;
} else {
avg = time_passed / 3;
}
print_row(RCV_NUM, avg, TTL, responses);
return DEST_REACHED;
}
int receive_from(int sockfd, char recipient[20], int PID, int TTL, char response[20])
{
struct sockaddr_in sender;
socklen_t sender_len = sizeof(sender);
u_int8_t buffer[IP_MAXPACKET];
ssize_t packet_len = recvfrom (sockfd, buffer, IP_MAXPACKET, 0, (struct sockaddr*)&sender, &sender_len);
if (packet_len < 0) {
fprintf(stderr, "recvfrom error: %s\n", strerror(errno));
return EXIT_FAILURE;
}
char sender_ip_str[20];
inet_ntop(AF_INET, &(sender.sin_addr), sender_ip_str, sizeof(sender_ip_str));
printf ("Received IP packet with ICMP content from: %s\n", sender_ip_str);
struct ip* ip_header = (struct ip*) buffer;
ssize_t ip_header_len = 4 * ip_header->ip_hl;
struct icmp* icmp_package = (struct icmp*)((uint8_t *)ip_header + ip_header_len);
u_int8_t icmp_Type = icmp_package->icmp_type;
u_int8_t icmp_Code = icmp_package->icmp_code;
//We reached the destination point
if(icmp_Type == 0 && icmp_Code == 0)
{
if(icmp_package->icmp_hun.ih_idseq.icd_id == (u_int16_t) PID && icmp_package->icmp_hun.ih_idseq.icd_id == (u_int16_t) TTL)
{
inet_ntop(AF_INET, &(sender.sin_addr), response, 20);
return 1;
}
}
//Time Exceeded - we are not yet in the destination point
if(icmp_Type == 11 && icmp_Code == 0)
{
struct ip* ip_header_md = (struct ip *)((uint8_t *)icmp_package + 8);
struct icmp* icmp_package_md = (struct icmp *)((uint8_t *)ip_header_md + (*ip_header_md).ip_hl * 4);
if(icmp_package_md->icmp_hun.ih_idseq.icd_id == (u_int16_t) PID && icmp_package_md->icmp_hun.ih_idseq.icd_id == (u_int16_t) TTL)
{
inet_ntop(AF_INET, &(sender.sin_addr), response, 20);
return 0;
}
}
//Błąd
return -1;
}

Stuck in a timeout loop from using alarm();

I'm attempting to implement a GoBackN protocol and when the server drops a packet, my alarm waits 2 seconds before sending all previously sent packets.
The alarm works and waits 2 seconds, however after the first timeout, the state machine I'm using gets stuck in a loop and continues to timeout. I think it might be because errno is not getting reset, but I'm not sure.
#define TIMEOUT_SECS 2
#define MAXTRIES 10
int base = 0;
int windowSize = 7;
int sendFlag = 1;
int tries = 0;
int numPackets = 0;
packet *packetArray[30];
void addPacket(packet *p)
{
for (int i = 0; i < 30; i++)
{
if (packetArray[i])
{
continue;
}
else
{
packetArray[i] = p;
numPackets++;
break;
}
}
}
void
CatchAlarm(int ignored) /* Handler for SIGALRM */
{
tries += 1;
errno = 0;
}
void
DieWithError()
{
printf("error");
exit (1);
}
int
max(int a, int b)
{
if (b > a)
return b;
return a;
}
int
min(int a, int b)
{
if(b>a)
return a;
return b;
}
typedef enum
{
wait,
sendData,
timeout,
receiveData
} e_state;
int main(int argumentCount, char *argumentVariables[])
{
//Grabbing all input information.
struct hostent *emulatorName;
emulatorName = gethostbyname(argumentVariables[1]);
int receiveFromEmulator = atoi(argumentVariables[3]);
int sendToEmulator = atoi(argumentVariables[2]);
//Setting up UDP socket for receiving from emulator.
int receiveSocket = 0;
receiveSocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
//UDP socket configuration.
struct sockaddr_in receiveSocketStruct;
bzero((char *) &receiveSocketStruct, sizeof(receiveSocketStruct));
receiveSocketStruct.sin_family = AF_INET;
receiveSocketStruct.sin_port = htons(receiveFromEmulator);
receiveSocketStruct.sin_addr.s_addr = INADDR_ANY;
socklen_t receiveSocketLen = sizeof(receiveSocketStruct);
//Binding UDP socket so client can locate emulator.
bind(receiveSocket, (struct sockaddr *)&receiveSocketStruct, sizeof(receiveSocketStruct));
//Setting up UDP socket for sending to emulator.
int sendSocket = 0;
sendSocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
//UDP socket configuration.
struct sockaddr_in sendSocketStruct;
bzero((char *) &sendSocketStruct, sizeof(sendSocketStruct));
sendSocketStruct.sin_family = AF_INET;
sendSocketStruct.sin_port = htons(sendToEmulator);
sendSocketStruct.sin_addr.s_addr = INADDR_ANY;
socklen_t sendSocketLen = sizeof(sendSocketStruct);
char buffer[1024];
std::ifstream infile (argumentVariables[4], std::ifstream::binary);
infile.seekg (0, infile.end);
int lengthOfFile = infile.tellg();
infile.seekg (0, infile.beg);
int totalPackets = 0;
int nextSeqNum = 0;
while(1)
{
if (lengthOfFile > 30)
{
bzero(buffer, 1024);
char * data = new char[1024];
infile.read(buffer, 30);
strncpy(data, buffer, 1024);
lengthOfFile -= 30;
if (nextSeqNum > 7)
{
nextSeqNum = 0;
}
addPacket(new packet(1, nextSeqNum, strlen(data), data));
totalPackets++;
nextSeqNum++;
}
else
{
bzero(buffer, 1024);
char * data = new char[1024];
infile.read(buffer, 30);
strncpy(data, buffer, 1024);
if (nextSeqNum > 7)
{
nextSeqNum = 0;
}
addPacket(new packet(1, nextSeqNum, strlen(data), data));
totalPackets++;
nextSeqNum++;
addPacket(new packet(3, nextSeqNum, 0, NULL));
totalPackets++;
break;
}
}
infile.close();
nextSeqNum = 0;
int packetsReceived;
int sentPackets;
int receive = 0;
char receivePayload[1024];
char sendPayload[1024];
struct sigaction myAction; /* For setting signal handler */
myAction.sa_handler = CatchAlarm;
if (sigfillset (&myAction.sa_mask) < 0) /* block everything in handler */
DieWithError ();
myAction.sa_flags = 0;
if (sigaction (SIGALRM, &myAction, 0) < 0)
DieWithError ();
e_state currentState = wait;
e_state previousState = wait;
while(1)
{
if (currentState == wait)
{
if (sendFlag == 1)
{
previousState = currentState;
currentState = sendData;
}
else
{
previousState = currentState;
currentState = receiveData;
}
}
else if (currentState == sendData)
{
if ((nextSeqNum < base + windowSize) && (nextSeqNum < totalPackets - 1))
{
//send packet with seqnum.
int sendPacket = 0;
bzero(sendPayload, 1024);
packet * sendpckt = packetArray[nextSeqNum];
sendpckt->serialize(sendPayload);
sendpckt->printContents();
sendPacket = sendto(sendSocket, sendPayload, sizeof(sendPayload), 0, (struct sockaddr *)&sendSocketStruct, sendSocketLen);
if (base == nextSeqNum)
{
alarm(0);
alarm(TIMEOUT_SECS);
}
nextSeqNum++;
}
else
{
sendFlag = 0;
previousState = currentState;
currentState = wait;
}
}
else if (currentState == timeout)
{
alarm(0);
alarm(TIMEOUT_SECS);
for(int counter = base; counter < nextSeqNum; counter++)
{
int sendPacket = 0;
bzero(sendPayload, 1024);
packet * sendpckt = packetArray[counter];
sendpckt->serialize(sendPayload);
sendpckt->printContents();
sendPacket = sendto(sendSocket, sendPayload, sizeof(sendPayload), 0, (struct sockaddr *)&sendSocketStruct, sendSocketLen);
}
sendFlag = 0;
previousState = currentState;
currentState = wait;
}
else if (currentState == receiveData)
{
bzero(receivePayload, 1024);
receive = (recvfrom(receiveSocket, receivePayload, sizeof(receivePayload), 0, (struct sockaddr *)&receiveSocketStruct, &receiveSocketLen));
if (errno == EINTR)
{
printf("timeout");
if (tries > MAXTRIES)
{
alarm(0);
break;
printf("recvfrom() failed.");
}
previousState = currentState;
currentState = timeout;
}
else
{
char buffer[1024];
bzero(buffer, 1024);
int receivePacketType;
int receivePacketSeqNum;
packet recvpckt(0, 0, 0, (char*)buffer);
recvpckt.deserialize((char*)receivePayload);
receivePacketSeqNum = recvpckt.getSeqNum();
receivePacketType = recvpckt.getType();
recvpckt.printContents();
if (receivePacketType == 2)
{
break;
}
base = receivePacketSeqNum + 1;
printf("%d\n", base);
if (base == nextSeqNum)
{
alarm(0);
}
else
{
alarm(0);
alarm(TIMEOUT_SECS);
}
if (nextSeqNum == totalPackets - 1)
{
nextSeqNum++;
int sendPacket = 0;
bzero(sendPayload, 1024);
packet * sendpckt = packetArray[nextSeqNum - 1];
sendpckt->serialize(sendPayload);
sendpckt->printContents();
sendPacket = sendto(sendSocket, sendPayload, sizeof(sendPayload), 0, (struct sockaddr *)&sendSocketStruct, sendSocketLen);
}
if (base <= totalPackets)
{
sendFlag = 1;
previousState = currentState;
currentState = wait;
}
else
{
continue;
}
}
}
else
{
break;
}
}
//Close shop.
close(receiveSocket);
close(sendSocket);
return 0;
}
The location where I suspect the loop to start is in the receiveData state.
Fixed it:
else if (currentState == receiveData)
{
receive = 0;
bzero(receivePayload, 1024);
receive = (recvfrom(receiveSocket, receivePayload, sizeof(receivePayload), 0, (struct sockaddr *)&receiveSocketStruct, &receiveSocketLen));
if (receive < 0)
{
printf("timeout");
if (tries > MAXTRIES)
{
alarm(0);
break;
printf("recvfrom() failed.");
}
previousState = currentState;
currentState = timeout;
}

c++ project wont connect to socket with error 10093

Why can't this program connect to the socket?
I know that WSAStartup fails, but I can't figure out how to use it.
#include "StdAfx.h"
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <winsock2.h>
#include <windows.h>
#include <ws2tcpip.h>
#include <string.h>
#include <errno.h>
#pragma comment(lib, "ws2_32.lib")
int sockd;
#define SocketErrno (WSAGetLastError())
#define bcopy(src,dest,len) memmove(dest,src,len)
typedef signed char int8;
typedef signed long int32;
inline int WriteInt8(char *buf, int pos, int8 value) { buf[pos] = (int8)(value); return 1; }
inline int WriteInt32(char *buf, int pos, int32 value) { buf[pos] = (int8)(value >> 24); buf[pos+1] = (int8)(value >> 16); buf[pos+2] = (int8)(value >> 8); buf[pos+3] = (int8)(value); return 4; }
inline int WriteASCII(char *start_buf, int pos, const char *start, int length) { int startPos = 0; char *buf = &start_buf[pos]; for (int i = 0; i < length; ++i) { buf[i] = start[startPos]; if (start[startPos]) ++startPos; } return length; }
size_t writen(int fd, const char *vptr, size_t n)
{
size_t nleft;
size_t nwritten;
const char *ptr;
ptr = vptr;
nleft = n;
while (nleft > 0)
{
if ( (nwritten = writen(fd, ptr, nleft)) <= 0)
{
if (errno == EINTR)
nwritten = 0;
else
return(-1);
}
nleft -= nwritten;
ptr += nwritten;
}
return(n);
}
bool login(char *Username, char *Password, int characterID)
{
char buffer[8192];
int pos = 0;
pos += WriteInt8(buffer, pos, 0x91u);
pos += WriteInt8(buffer, pos, 58);
pos += WriteInt8(buffer, pos, 0xFFu);
pos += WriteInt8(buffer, pos, 55);
pos += WriteInt8(buffer, pos, 40);
pos += WriteASCII(buffer, pos, Username, 30);
pos += WriteASCII(buffer, pos, Password, 30);
if( writen(sockd, buffer, 65) < 65)
return false;
WriteInt8(buffer, 0, 0x5D);
WriteInt32(buffer, 65, characterID);
if( writen(sockd, buffer, 73) < 73)
return false;
return true;
}
bool connect(char *ServerAddress, int ServerPort)
{
struct sockaddr_in servaddr;
if ( (sockd = socket(AF_INET, SOCK_STREAM, 0)) < 0 )
return false;
memset(&servaddr, 0, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(ServerPort);
if ( inet_pton(AF_INET, ServerAddress, &servaddr.sin_addr) <= 0 )
return false;
if ( connect(sockd, (struct sockaddr *) &servaddr, sizeof(servaddr)) < 0 )
return false;
char seed[4] = { 0x3au, 0xFFu, 55, 40 };
if( writen(sockd, seed, 4) < 0)
return false;
return true;
}
int main(int argc, char * argv[])
{
bool wArgs = true;
if (argc == 1)
{
wArgs = false;
}
else if (argc != 4)
{
printf("USAGE: %s User Password CharacterNumber\n", argv[0]);
return 51;
}
printf("stuff");
char *user = new char[20];
char *pass = new char[20];
int pg;
if (wArgs)
{
user = argv[1];
pass = argv[2];
pg = atoi(argv[3]);
}
else
{
printf("*****************************************\n\nUser: ");
scanf("%s", user);
printf("Pass: ");
scanf("%s", pass);
printf("Character Number: ");
scanf("%d", &pg);
printf("\n*****************************************\n");
}
if (!connect("ip hidden,port hidden))
{
printf("Error at socket(): %ld\n", WSAGetLastError());
return 1;
}
if (!login(user, pass, pg))
return 103;
char version[12] = { 0xBDu, 0x00u, 0x0Cu, 0x36u, 0x2Eu, 0x30u, 0x2Eu, 0x31u, 0x2Eu, 0x31u, 0x30u, 0x00 };
if ( writen(sockd, version, 12) < 0 )
return 105;
for(;;)
{
//12 00 09 24 32 31 20 30 00 ...l.....$21 0.
char refresh[9] = { 0x12, 0x00, 0x09, 0x24, 0x32, 0x31, 0x20, 0x30, 0x00 };
if( writen(sockd, refresh, 9) < 0)
return 104;
Sleep(40);
}
return 1;
}
10093 is WSANOTINITIALISED, which means WSAStartup() has not been called yet. The documentation for WSAStartup is pretty clear, if a bit verbose, and even includes a fairly complete example.
You must call WSAStartup before using any other Winsock functions:
wVersionRequested = MAKEWORD(2, 2);
err = WSAStartup(wVersionRequested, &wsaData);
You may also want to checkout out the WinSock FAQ when learning to do WinSock programming.

trying to receive a file over socket

sending and recieving file from tcp socket. Sending the file works however trying to save the file does not work.
#include <cassert>
#include <arpa/inet.h>
#include <cstdlib>
#include <iostream>
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <errno.h>
#include <string.h>
#include <fstream>
#include <time.h>
#include <strings.h>
#include <sstream>
#include <vector>
#include <netdb.h>
#include <netinet/in.h>
#include <sys/sendfile.h>
#include <fcntl.h>
using namespace std;
using std::endl;
int newscount = 0;
int doccount = 0;
int photocount = 0;
int johns = 0;
vector<string> newsvector;
vector<string> photosvector;
vector<string> docsvector;
void serverlogs(const char*msg) /* writing to log file */
{
time_t rawtime;
struct tm * timeinfo;
time (&rawtime);
timeinfo = localtime(&rawtime);
ofstream file;
file.open("serverlog.txt",ios::app);
if (file.is_open())
{file<<msg;
file<<" # ";
file<<asctime(timeinfo);
file<<"\n";
file.close();
return;
}
else
cout<<"Error Creating log file";
return;
}
void clientlogs(const char*msg) /* writing to log file */
{
time_t rawtime;
struct tm * timeinfo;
time (&rawtime);
timeinfo = localtime(&rawtime);
ofstream file;
file.open("clientlog.txt",ios::app);
if (file.is_open())
{file<<msg;
file<<" # ";
file<<asctime(timeinfo);
file<<"\n";
file.close();
return;
}
else
cout<<"Error Creating log file";
return;
}
void error(const char*msg) /* If there is an error exit the program with err# 1 */
{
perror(msg);
exit(1);
}
void publishdocsvector(const char*msg)
{
docsvector.push_back(msg);
ofstream file;
file.open("docfiles.txt",ios::app);
if (file.is_open())
{
for(int j = 0; j < docsvector.size() ;j++)
{file<<docsvector[j];}
file.close();
}
else
cout<<"Error creating news archive";
return;
}
void publishphotosvector(const char*msg)
{
photosvector.push_back(msg);
ofstream file;
file.open("photofiles.txt",ios::app);
if (file.is_open())
{
for(int j = 0; j < photosvector.size() ;j++)
{file<<photosvector[j];}
file.close();
}
else
cout<<"Error creating news archive";
return;
}
void publishnewsvector(const char*msg)
{
newsvector.push_back(msg);
ofstream file;
file.open("newsfiles.txt",ios::app);
if (file.is_open())
{
for(int j = 0; j < newsvector.size() ;j++)
{file<<newsvector[j];}
file.close();
}
else
cout<<"Error creating news archive";
return;
}
void sendfile(const char*msg)
{
// to be implemented later//
}
int main (int argc, char*argv[]) /*Main Program accepting a port number and something else for arguments */
{
int sockfd, newsockfd, portno, clilen, n,test;
string publish="publish";
string search= "search";
string get="get";
string newsstring = "news";
string docstring = "doc";
string photostring = "photo";
string wrap = "exit";
char buffer[256];
char seats [50];
serverlogs("Server Running");
struct sockaddr_in serv_addr, cli_addr; /* Defines the server address and client address and types of structures with the same format as socket address */
if (argc < 2)
{
fprintf(stderr,"Please provide a port number next time plz, goodbye!");
exit(1);
}
sockfd = socket(AF_INET, SOCK_STREAM, 0); /* If Sock_Dgram then then it will open a udp socket */
if (sockfd < 0)
error("Error opening socket");
bzero((char *)&serv_addr, sizeof(serv_addr)); /* sets the server address to zero usings its reference */
portno = atoi(argv[1]); /*2nd argument vector is the port number and converted into an integer, the first [0] is the running program */
serv_addr.sin_family = AF_INET; /* The structure sockaddr_in has four fields, this is first one and should always be this */
serv_addr.sin_port = htons(portno); /* convert port number into network byte order */
serv_addr.sin_addr.s_addr = INADDR_ANY; /*3rd Field uses Ip address of host machine */
if (bind(sockfd,(struct sockaddr *) &serv_addr, sizeof(serv_addr))<0) /*bind socket to sockfd and address of server ,and needs size of address need struct of sockaddr, see bind man for details*/
error("Couldn't bind socket to address");
listen(sockfd,5);
clilen = sizeof(cli_addr);
serverlogs("going into server loop");
int pid = fork();
if (pid < 0)
serverlogs("error on initial separtion of server and client");
if (pid==0)
{
// server loop later on this will be the child process and client will be main
while (1)
{ /* Server loop loop*/
newsockfd = accept(sockfd,(struct sockaddr *) &cli_addr, (socklen_t*)&clilen);
if (newsockfd < 0)
/* error("Corrupt log"); */
serverlogs("Connection not accepted");
else (newsockfd > 0);
int ppID = fork();
if (ppID < 0)
serverlogs("A new server process failed to be created");
if (ppID == 0)
{
int uid;
uid = johns;
printf("A new client connected with identity: %d\n", getpid());
close(sockfd);
serverlogs("A john Connected to the server");
printf("my unique id: %d\n", uid);
serverlogs(seats);
bzero(buffer,256);
//n = write(newsockfd,"Each client is a 'john' \n",26);
/* This loop read from socket and writes to other persons sockets */
while(1)
{
bzero(buffer,256);
n = read(newsockfd,buffer,256);
if (n < 0)
printf ("error reading from socket here is the message: %s",buffer);
if (publish[0] == buffer[0])
{
n = write(newsockfd,"What category are you publishing in?(news,photos,documents) \n",62);
bzero(buffer,256);
n = read(newsockfd,buffer,256);
if(buffer[0]==newsstring[0])
{
n = write(newsockfd,"Type the name of the file to publish and wait 10 seconds \n",59);
bzero(buffer,256);
n = read(newsockfd,buffer,256);
publishnewsvector(buffer);
serverlogs(seats);
serverlogs("client is trying to publish a news file:");
serverlogs(buffer);
/*start recieving a file*/
std::ofstream file;
file.open(buffer, std::ios::out | std::ios::binary);
assert(file.is_open());
while (1) {
std::cout << "..";
bzero(buffer,256);
n = read(newsockfd, buffer, sizeof(buffer));
assert(n != -1);
if (n == 0)
break;
file.write(buffer, n);
i++;
}
file.close();
serverlogs("File Transfered successfully");
}
if(buffer[0]==docstring[0])
{
n = write(newsockfd,"Type the name of the file to publish \n",39);
bzero(buffer,256);
n = read(newsockfd,buffer,256);
publishdocsvector(buffer);
serverlogs(seats);
serverlogs("client is tyring to publish a document:" );
serverlogs(buffer);
/*start recieving a file*/
std::ofstream file;
file.open(buffer, std::ios::out | std::ios::binary);
assert(file.is_open());
while (1) {
std::cout << ".";
bzero(buffer,256);
n = read(newsockfd, buffer, sizeof(buffer));
assert(n != -1);
if (n == 0)
break;
file.write(buffer, n);
}
file.close();
serverlogs("File Transfered successfully");
}
if(buffer[0]==photostring[0])
{
n = write(newsockfd,"Type the name of the file to publish \n",39);
bzero(buffer,256);
n = read(newsockfd,buffer,256);
publishphotosvector(buffer);
serverlogs(seats);
serverlogs("client is trying to publish photo file:" );
serverlogs(buffer);
/*start recieving a file*/
std::ofstream file;
file.open(buffer, std::ios::out | std::ios::binary);
assert(file.is_open());
while (1) {
std::cout << ".";
bzero(buffer,256);
n = read(newsockfd, buffer, sizeof(buffer));
assert(n != -1);
if (n == 0)
break;
file.write(buffer, n);
}
file.close();
serverlogs("File Transfered successfully");
}
}
if (get[0] ==buffer[0])
{
n = write(newsockfd,"\n What file do you want to get? \n",35);
bzero(buffer,256);
n = read(newsockfd,buffer,256);
serverlogs(seats);
serverlogs("client wants file:");
serverlogs(buffer);
//** start sending the file**//
FILE* searchfile = 0;
long Size = 0;
searchfile = fopen(buffer,"r");
fseek(searchfile, 0, SEEK_END);
Size = ftell(searchfile);
char *bufferfile = (char*)malloc(Size);
memset(bufferfile, 0, Size);
fseek(searchfile, 0, SEEK_SET);
fread(bufferfile, Size, 1, searchfile);
n = write(newsockfd,bufferfile,256);
fclose(searchfile);
serverlogs("Sent the file to the client");
serverlogs(seats);
}
if (search[0] == buffer[0])
{
bzero(buffer,256);
n = write(newsockfd,"What category are you searching? \n",35);
bzero(buffer,256);
n = read(newsockfd,buffer,256);
serverlogs(seats);
serverlogs("client searching for");
serverlogs(buffer);
if(buffer[0]==newsstring[0])
{
FILE* searchfile = 0;
long Size = 0;
searchfile = fopen("newsfiles.txt","r");
fseek(searchfile, 0, SEEK_END);
Size = ftell(searchfile);
char *bufferfile = (char*)malloc(Size);
memset(bufferfile, 0, Size);
fseek(searchfile, 0, SEEK_SET);
fread(bufferfile, Size, 1, searchfile);
n = write(newsockfd,bufferfile,256);
fclose(searchfile);
}
if(buffer[0]==docstring[0])
{
FILE* searchfile = 0;
long Size = 0;
searchfile = fopen("docfiles.txt","r");
fseek(searchfile, 0, SEEK_END);
Size = ftell(searchfile);
char *bufferfile = (char*)malloc(Size);
memset(bufferfile, 0, Size);
fseek(searchfile, 0, SEEK_SET);
fread(bufferfile, Size, 1, searchfile);
n = write(newsockfd,bufferfile,256);
fclose(searchfile);
}
if(buffer[0]==photostring[0])
{
FILE* searchfile = 0;
long Size = 0;
searchfile = fopen("photofiles.txt","r");
fseek(searchfile, 0, SEEK_END);
Size = ftell(searchfile);
char *bufferfile = (char*)malloc(Size);
memset(bufferfile, 0, Size);
fseek(searchfile, 0, SEEK_SET);
fread(bufferfile, Size, 1, searchfile);
n = write(newsockfd,bufferfile,256);
fclose(searchfile);
}
}
if(buffer[0]==wrap[0])
{
close(sockfd);
close(newsockfd);
johns = johns - 1;
serverlogs("A john left");
return 0;
}
n = write(newsockfd,"\n Waiting for a command I can understand:(publish,search,get,exit)",66);
} /* while loop to listen to commands from client bracket */
}/*what to do when client connected*/
} /*Creating child/zombies */
} /* division between client and server*/
else
{
while (1)
{int ssockfd, pportno, p,peer;
struct sockaddr_in peer_addr;
struct hostent *peerserver;
char bbuffer[256];
printf ("%s \n", "Welcome to the Social");
printf ("%s \n", "Please type the port number of the server \n");
cin>>pportno;
ssockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0)
error("ERROR opening socket Please try again");
printf ("%s \n", "Please type in the hostname of client ie sunlab1.njit.edu \n");
char peers[256];
cin >> peers;
peerserver = gethostbyname(peers);
if (peerserver == NULL)
{
fprintf(stderr,"could not connect to ip address");
peerserver = gethostbyname((const char*)peer);
if (peerserver == NULL)
fprintf(stderr,"still null");
exit(0);
}
bzero((char *) &peer_addr, sizeof(peer_addr));
peer_addr.sin_family = AF_INET;
bcopy((char *)peerserver->h_addr,(char *)&peer_addr.sin_addr.s_addr,peerserver->h_length);
peer_addr.sin_port = htons(pportno);
if (connect(ssockfd,(struct sockaddr *)&peer_addr,sizeof(peer_addr)) < 0)
error("ERROR connecting");
clientlogs("Connected to peer");
clientlogs((const char*)&peer);
printf("Please enter a command, publish,search or get: ");
while (1)
{
bzero(bbuffer,256);
fgets(bbuffer,255,stdin);
char apub[] = "publish";
char asearch[] = "search";
char aget[]="get";
if (bbuffer[0]==apub[0] && bbuffer[1]==apub[1])
{
p = write(ssockfd,bbuffer,strlen(bbuffer));
if (p < 0)
error("ERROR writing to socket");
bzero(bbuffer,256);
p = read(ssockfd,bbuffer,255);
if (p < 0)
error("ERROR reading from socket");
printf("%s",bbuffer); //What category are you publishing in//
bzero(bbuffer,256);
fgets(bbuffer,255,stdin);
p = write(ssockfd,bbuffer,strlen(bbuffer));
clientlogs("Client publishing");
clientlogs(bbuffer);
if (p < 0)
error("ERROR writing to socket");
bzero(bbuffer,256);
p = read(ssockfd,bbuffer,255);
if (p < 0)
error("ERROR reading from socket");
printf("%s",bbuffer); //Type the name of the file//
fgets(bbuffer,255,stdin);
p = write(ssockfd,bbuffer,strlen(bbuffer));
clientlogs(bbuffer);
FILE* searchfile = 0;
long Size = 0;
searchfile = fopen(bbuffer,"r");
fseek(searchfile, 0, SEEK_END);
Size = ftell(searchfile);
char *bufferfile = (char*)malloc(Size);
memset(bufferfile, 0, Size);
fseek(searchfile, 0, SEEK_SET);
fread(bufferfile, Size, 1, searchfile);
p = write(ssockfd,bufferfile,256);
fclose(searchfile);
}
if(bbuffer[0]==aget[0] && bbuffer[1]==aget[1])
{
p = write(ssockfd,bbuffer,strlen(bbuffer));
if (p < 0)
error("ERROR writing to socket");
bzero(bbuffer,256);
p = read(ssockfd,bbuffer,255);
if (p < 0)
error("ERROR reading from socket");
printf("%s",bbuffer); //What file do you want to get? //
bzero(bbuffer,256);
fgets(bbuffer,255,stdin);
p = write(ssockfd,bbuffer,strlen(bbuffer));
if (p < 0)
error("ERROR writing to socket");
clientlogs("client wants file:");
clientlogs(bbuffer);
/*start recieving a file*/
std::ofstream file;
file.open(bbuffer, std::ios::out | std::ios::binary);
assert(file.is_open());
char buffer[255];
while (1) {
std::cout << ".";
bzero(bbuffer,256);
p = read(ssockfd, bbuffer, sizeof(bbuffer));
assert(p != -1);
if (p == 0)
break;
file.write(bbuffer, p);
}
file.close();
serverlogs("File Transfered successfully");
}
if (bbuffer[0]==asearch[0] && bbuffer[1]==asearch[1])
{
p = write(ssockfd,bbuffer,strlen(bbuffer));
if (p < 0)
error("ERROR writing to socket");
bzero(bbuffer,256);
p = read(ssockfd,bbuffer,255);
if (p < 0)
error("ERROR reading from socket");
printf("%s",bbuffer); // what category? //
fgets(bbuffer,255,stdin);
p = write(ssockfd,bbuffer,strlen(bbuffer));
if (p < 0)
error("ERROR writing to socket");
clientlogs("Client searching for file");
clientlogs(bbuffer);
bzero(bbuffer,256);
p = read(ssockfd,bbuffer,255);
if (p < 0)
error("ERROR reading from socket");
printf("%s",bbuffer); //The vector array of the files //
}
if (bbuffer[0]==wrap[0] && bbuffer[1]==wrap[1])
{ p = write(ssockfd,bbuffer,strlen(bbuffer));
exit(0); }
}//end of client loop asking to enter a command
}
}
return 0;
}
The problem I see is file << bbuffer. The ofstream's << operator writes until the first NULL byte. Don't forget your buffer is a string (or better, a char *). So, if bbuffer doesn't contain a NULL byte, your program is likely to crash with a SIGSEGV.
You should use file.write(bbuffer, p) instead of file << bbuffer. Also, there's no need to cleanup your buffer using bzero or memset.
And since you didn't provide a compilable source, I wrote the following (supposing Linux/Unix):
#include <cassert>
#include <iostream>
#include <fstream>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
int main() {
int fd = socket(AF_INET, SOCK_STREAM, 0);
struct sockaddr_in sa_dst;
memset(&sa_dst, 0, sizeof(struct sockaddr_in));
sa_dst.sin_family = AF_INET;
sa_dst.sin_port = htons(1234);
sa_dst.sin_addr.s_addr = inet_addr("127.0.0.1");
int ret = connect(fd, (struct sockaddr *)&sa_dst, sizeof(struct sockaddr));
assert(ret != -1);
std::ofstream file;
file.open("received.bin", std::ios::out | std::ios::binary);
assert(file.is_open());
char buffer[255];
while (1) {
std::cout << "..";
ssize_t p = read(fd, buffer, sizeof(buffer));
assert(p != -1);
if (p == 0)
break;
file.write(buffer, p);
}
file.close();
}
You can test it using netcat on your terminal:
$ nc -l 1234 < some_binary_file &
$ ./program
$ cmp some_binary_file received.bin