libusb failing at getting string descriptor on some devices - c++

I am trying to get information about all attached devices.
This is my code:
libusb_device_descriptor desc;
libusb_config_descriptor *conDesc;
char szBuffer[256] = { 0 };
unsigned char strDesc[256];
libusb_device_handle *devHandle = NULL;
int retVal = 0;
__int64 i64Temp;
DWORD dwProdId;
DWORD dwProdId1;
i64Temp = 13888;
dwProdId = (DWORD)i64Temp;
retVal = libusb_open(dev, &devHandle);
int r = libusb_get_device_descriptor(dev, &desc);
if (r < 0)
{
cout << "failed to get device descriptor" << endl;
return;
}
r = libusb_get_config_descriptor(dev, 0, &conDesc);
printf("Interface Class = %d\n", conDesc->interface->altsetting->bInterfaceClass);
cout << "Number of possible configurations: " << (int)desc.bNumConfigurations << "" << endl;
cout << "Device Class: " << desc.bDeviceClass << endl;
cout << "Device Class: " << desc.bDeviceSubClass << endl;
printf("Class = %d\n", desc.bDeviceClass);
cout << "VendorID: " << desc.idVendor << endl;
cout << "ProductID: " << desc.idProduct << endl;
if (retVal == LIBUSB_SUCCESS)
{
retVal = libusb_get_string_descriptor_ascii(devHandle, desc.iManufacturer, strDesc, 256);
printf("Manufacturer: %s\n", strDesc);
retVal = libusb_get_string_descriptor_ascii(devHandle, desc.iSerialNumber, strDesc, 256);
printf("SerialNumber: %s\n", strDesc);
retVal = libusb_get_string_descriptor_ascii(devHandle, desc.iProduct, strDesc, 256);
printf("Product: %s\n", strDesc);
printf("\n\n");
}
else if (retVal != LIBUSB_SUCCESS)
{
printf("retVal failed");
printf("\n\n");
}
My code knows that there are 8 devices connected but it's getting manufacturer or serial number only on two of them. I would like to get this information for all of the attached devices.

Related

audio do not stop recording after pause ffmpeg c++

I am developing an application that record the screen and the audio from microphone. I implemented the pause function stopping video and audio thread on a condition variable, resuming them with a notify on the same condition variable. This is done in captureAudio(), in the main while. In this way works on macOS and linux, where I use avfoudation and alsa respectively, but on windows, with dshow, keep recording audio during the pause, when the thread is waiting on the condition variable. Does anybody know how can I fix this behaviour?
#include "ScreenRecorder.h"
using namespace std;
ScreenRecorder::ScreenRecorder() : pauseCapture(false), stopCapture(false), started(false), activeMenu(true) {
avcodec_register_all();
avdevice_register_all();
width = 1920;
height = 1200;
}
ScreenRecorder::~ScreenRecorder() {
if (started) {
value = av_write_trailer(outAVFormatContext);
if (value < 0) {
cerr << "Error in writing av trailer" << endl;
exit(-1);
}
avformat_close_input(&inAudioFormatContext);
if(inAudioFormatContext == nullptr){
cout << "inAudioFormatContext close successfully" << endl;
}
else{
cerr << "Error: unable to close the inAudioFormatContext" << endl;
exit(-1);
//throw "Error: unable to close the file";
}
avformat_free_context(inAudioFormatContext);
if(inAudioFormatContext == nullptr){
cout << "AudioFormat freed successfully" << endl;
}
else{
cerr << "Error: unable to free AudioFormatContext" << endl;
exit(-1);
}
avformat_close_input(&pAVFormatContext);
if (pAVFormatContext == nullptr) {
cout << "File close successfully" << endl;
}
else {
cerr << "Error: unable to close the file" << endl;
exit(-1);
//throw "Error: unable to close the file";
}
avformat_free_context(pAVFormatContext);
if (pAVFormatContext == nullptr) {
cout << "VideoFormat freed successfully" << endl;
}
else {
cerr << "Error: unable to free VideoFormatContext" << endl;
exit(-1);
}
}
}
/*==================================== VIDEO ==============================*/
int ScreenRecorder::openVideoDevice() throw() {
value = 0;
options = nullptr;
pAVFormatContext = nullptr;
pAVFormatContext = avformat_alloc_context();
string dimension = to_string(width) + "x" + to_string(height);
av_dict_set(&options, "video_size", dimension.c_str(), 0); //option to set the dimension of the screen section to record
#ifdef _WIN32
pAVInputFormat = av_find_input_format("gdigrab");
if (avformat_open_input(&pAVFormatContext, "desktop", pAVInputFormat, &options) != 0) {
cerr << "Couldn't open input stream" << endl;
exit(-1);
}
#elif defined linux
int offset_x = 0, offset_y = 0;
string url = ":0.0+" + to_string(offset_x) + "," + to_string(offset_y); //custom string to set the start point of the screen section
pAVInputFormat = av_find_input_format("x11grab");
value = avformat_open_input(&pAVFormatContext, url.c_str(), pAVInputFormat, &options);
if (value != 0) {
cerr << "Error in opening input device (video)" << endl;
exit(-1);
}
#else
value = av_dict_set(&options, "pixel_format", "0rgb", 0);
if (value < 0) {
cerr << "Error in setting pixel format" << endl;
exit(-1);
}
value = av_dict_set(&options, "video_device_index", "1", 0);
if (value < 0) {
cerr << "Error in setting video device index" << endl;
exit(-1);
}
pAVInputFormat = av_find_input_format("avfoundation");
if (avformat_open_input(&pAVFormatContext, "Capture screen 0:none", pAVInputFormat, &options) != 0) { //TODO trovare un modo per selezionare sempre lo schermo (forse "Capture screen 0")
cerr << "Error in opening input device" << endl;
exit(-1);
}
#endif
//set frame per second
value = av_dict_set(&options, "framerate", "30", 0);
if (value < 0) {
cerr << "Error in setting dictionary value (setting framerate)" << endl;
exit(-1);
}
value = av_dict_set(&options, "preset", "medium", 0);
if (value < 0) {
cerr << "Error in setting dictionary value (setting preset value)" << endl;
exit(-1);
}
/*
value = av_dict_set(&options, "vsync", "1", 0);
if(value < 0){
cerr << "Error in setting dictionary value (setting vsync value)" << endl;
exit(-1);
}
*/
value = av_dict_set(&options, "probesize", "60M", 0);
if (value < 0) {
cerr << "Error in setting probesize value" << endl;
exit(-1);
}
//get video stream infos from context
value = avformat_find_stream_info(pAVFormatContext, nullptr);
if (value < 0) {
cerr << "Error in retrieving the stream info" << endl;
exit(-1);
}
VideoStreamIndx = -1;
for (int i = 0; i < pAVFormatContext->nb_streams; i++) {
if (pAVFormatContext->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
VideoStreamIndx = i;
break;
}
}
if (VideoStreamIndx == -1) {
cerr << "Error: unable to find video stream index" << endl;
exit(-2);
}
pAVCodecContext = pAVFormatContext->streams[VideoStreamIndx]->codec;
pAVCodec = avcodec_find_decoder(pAVCodecContext->codec_id/*params->codec_id*/);
if (pAVCodec == nullptr) {
cerr << "Error: unable to find decoder video" << endl;
exit(-1);
}
cout << "Insert height and width [h w]: "; //custom screen dimension to record
cin >> h >> w;*/
return 0;
}
/*========================================== AUDIO ============================*/
int ScreenRecorder::openAudioDevice() {
audioOptions = nullptr;
inAudioFormatContext = nullptr;
inAudioFormatContext = avformat_alloc_context();
value = av_dict_set(&audioOptions, "sample_rate", "44100", 0);
if (value < 0) {
cerr << "Error: cannot set audio sample rate" << endl;
exit(-1);
}
value = av_dict_set(&audioOptions, "async", "1", 0);
if (value < 0) {
cerr << "Error: cannot set audio sample rate" << endl;
exit(-1);
}
#if defined linux
audioInputFormat = av_find_input_format("alsa");
value = avformat_open_input(&inAudioFormatContext, "hw:0", audioInputFormat, &audioOptions);
if (value != 0) {
cerr << "Error in opening input device (audio)" << endl;
exit(-1);
}
#endif
#if defined _WIN32
audioInputFormat = av_find_input_format("dshow");
value = avformat_open_input(&inAudioFormatContext, "audio=Microfono (Realtek(R) Audio)", audioInputFormat, &audioOptions);
if (value != 0) {
cerr << "Error in opening input device (audio)" << endl;
exit(-1);
}
#endif
value = avformat_find_stream_info(inAudioFormatContext, nullptr);
if (value != 0) {
cerr << "Error: cannot find the audio stream information" << endl;
exit(-1);
}
audioStreamIndx = -1;
for (int i = 0; i < inAudioFormatContext->nb_streams; i++) {
if (inAudioFormatContext->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
audioStreamIndx = i;
break;
}
}
if (audioStreamIndx == -1) {
cerr << "Error: unable to find audio stream index" << endl;
exit(-2);
}
}
int ScreenRecorder::initOutputFile() {
value = 0;
outAVFormatContext = nullptr;
outputAVFormat = av_guess_format(nullptr, "output.mp4", nullptr);
if (outputAVFormat == nullptr) {
cerr << "Error in guessing the video format, try with correct format" << endl;
exit(-5);
}
avformat_alloc_output_context2(&outAVFormatContext, outputAVFormat, outputAVFormat->name, "..\\media\\output.mp4");
if (outAVFormatContext == nullptr) {
cerr << "Error in allocating outAVFormatContext" << endl;
exit(-4);
}
/*===========================================================================*/
this->generateVideoStream();
this->generateAudioStream();
//create an empty video file
if (!(outAVFormatContext->flags & AVFMT_NOFILE)) {
if (avio_open2(&outAVFormatContext->pb, "..\\media\\output.mp4", AVIO_FLAG_WRITE, nullptr, nullptr) < 0) {
cerr << "Error in creating the video file" << endl;
exit(-10);
}
}
if (outAVFormatContext->nb_streams == 0) {
cerr << "Output file does not contain any stream" << endl;
exit(-11);
}
value = avformat_write_header(outAVFormatContext, &options);
if (value < 0) {
cerr << "Error in writing the header context" << endl;
exit(-12);
}
return 0;
}
/*=================================== VIDEO ==================================*/
void ScreenRecorder::generateVideoStream() {
//Generate video stream
videoSt = avformat_new_stream(outAVFormatContext, nullptr);
if (videoSt == nullptr) {
cerr << "Error in creating AVFormatStream" << endl;
exit(-6);
}
outVideoCodec = avcodec_find_encoder(AV_CODEC_ID_MPEG4); //AV_CODEC_ID_MPEG4
if (outVideoCodec == nullptr) {
cerr << "Error in finding the AVCodec, try again with the correct codec" << endl;
exit(-8);
}
avcodec_alloc_context3(outAVCodec)
outVideoCodecContext = avcodec_alloc_context3(outVideoCodec);
if (outVideoCodecContext == nullptr) {
cerr << "Error in allocating the codec context" << endl;
exit(-7);
}
//set properties of the video file (stream)
outVideoCodecContext = videoSt->codec;
outVideoCodecContext->codec_id = AV_CODEC_ID_MPEG4;
outVideoCodecContext->codec_type = AVMEDIA_TYPE_VIDEO;
outVideoCodecContext->pix_fmt = AV_PIX_FMT_YUV420P;
outVideoCodecContext->bit_rate = 10000000;
outVideoCodecContext->width = width;
outVideoCodecContext->height = height;
outVideoCodecContext->gop_size = 10;
outVideoCodecContext->global_quality = 500;
outVideoCodecContext->max_b_frames = 2;
outVideoCodecContext->time_base.num = 1;
outVideoCodecContext->time_base.den = 30;
outVideoCodecContext->bit_rate_tolerance = 400000;
if (outVideoCodecContext->codec_id == AV_CODEC_ID_H264) {
av_opt_set(outVideoCodecContext->priv_data, "preset", "slow", 0);
}
if (outAVFormatContext->oformat->flags & AVFMT_GLOBALHEADER) {
outVideoCodecContext->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
}
value = avcodec_open2(outVideoCodecContext, outVideoCodec, nullptr);
if (value < 0) {
cerr << "Error in opening the AVCodec" << endl;
exit(-9);
}
outVideoStreamIndex = -1;
for (int i = 0; i < outAVFormatContext->nb_streams; i++) {
if (outAVFormatContext->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_UNKNOWN) {
outVideoStreamIndex = i;
}
}
if (outVideoStreamIndex < 0) {
cerr << "Error: cannot find a free stream index for video output" << endl;
exit(-1);
}
avcodec_parameters_from_context(outAVFormatContext->streams[outVideoStreamIndex]->codecpar, outVideoCodecContext);
}
/*=============================== AUDIO ==================================*/
void ScreenRecorder::generateAudioStream() {
AVCodecParameters* params = inAudioFormatContext->streams[audioStreamIndx]->codecpar;
inAudioCodec = avcodec_find_decoder(params->codec_id);
if (inAudioCodec == nullptr) {
cerr << "Error: cannot find the audio decoder" << endl;
exit(-1);
}
inAudioCodecContext = avcodec_alloc_context3(inAudioCodec);
if (avcodec_parameters_to_context(inAudioCodecContext, params) < 0) {
cout << "Cannot create codec context for audio input" << endl;
}
value = avcodec_open2(inAudioCodecContext, inAudioCodec, nullptr);
if (value < 0) {
cerr << "Error: cannot open the input audio codec" << endl;
exit(-1);
}
//Generate audio stream
outAudioCodecContext = nullptr;
outAudioCodec = nullptr;
int i;
AVStream* audio_st = avformat_new_stream(outAVFormatContext, nullptr);
if (audio_st == nullptr) {
cerr << "Error: cannot create audio stream" << endl;
exit(1);
}
outAudioCodec = avcodec_find_encoder(AV_CODEC_ID_AAC);
if (outAudioCodec == nullptr) {
cerr << "Error: cannot find requested encoder" << endl;
exit(1);
}
outAudioCodecContext = avcodec_alloc_context3(outAudioCodec);
if (outAudioCodecContext == nullptr) {
cerr << "Error: cannot create related VideoCodecContext" << endl;
exit(1);
}
if ((outAudioCodec)->supported_samplerates) {
outAudioCodecContext->sample_rate = (outAudioCodec)->supported_samplerates[0];
for (i = 0; (outAudioCodec)->supported_samplerates[i]; i++) {
if ((outAudioCodec)->supported_samplerates[i] == inAudioCodecContext->sample_rate)
outAudioCodecContext->sample_rate = inAudioCodecContext->sample_rate;
}
}
outAudioCodecContext->codec_id = AV_CODEC_ID_AAC;
outAudioCodecContext->sample_fmt = (outAudioCodec)->sample_fmts ? (outAudioCodec)->sample_fmts[0] : AV_SAMPLE_FMT_FLTP;
outAudioCodecContext->channels = inAudioCodecContext->channels;
outAudioCodecContext->channel_layout = av_get_default_channel_layout(outAudioCodecContext->channels);
outAudioCodecContext->bit_rate = 96000;
outAudioCodecContext->time_base = { 1, inAudioCodecContext->sample_rate };
outAudioCodecContext->strict_std_compliance = FF_COMPLIANCE_EXPERIMENTAL;
if ((outAVFormatContext)->oformat->flags & AVFMT_GLOBALHEADER) {
outAudioCodecContext->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
}
if (avcodec_open2(outAudioCodecContext, outAudioCodec, nullptr) < 0) {
cerr << "error in opening the avcodec" << endl;
exit(1);
}
//find a free stream index
outAudioStreamIndex = -1;
for (i = 0; i < outAVFormatContext->nb_streams; i++) {
if (outAVFormatContext->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_UNKNOWN) {
outAudioStreamIndex = i;
}
}
if (outAudioStreamIndex < 0) {
cerr << "Error: cannot find a free stream for audio on the output" << endl;
exit(1);
}
avcodec_parameters_from_context(outAVFormatContext->streams[outAudioStreamIndex]->codecpar, outAudioCodecContext);
}
int ScreenRecorder::init_fifo()
{
/* Create the FIFO buffer based on the specified output sample format. */
if (!(fifo = av_audio_fifo_alloc(outAudioCodecContext->sample_fmt,
outAudioCodecContext->channels, 1))) {
fprintf(stderr, "Could not allocate FIFO\n");
return AVERROR(ENOMEM);
}
return 0;
}
int ScreenRecorder::add_samples_to_fifo(uint8_t** converted_input_samples, const int frame_size) {
int error;
/* Make the FIFO as large as it needs to be to hold both,
* the old and the new samples. */
if ((error = av_audio_fifo_realloc(fifo, av_audio_fifo_size(fifo) + frame_size)) < 0) {
fprintf(stderr, "Could not reallocate FIFO\n");
return error;
}
/* Store the new samples in the FIFO buffer. */
if (av_audio_fifo_write(fifo, (void**)converted_input_samples, frame_size) < frame_size) {
fprintf(stderr, "Could not write data to FIFO\n");
return AVERROR_EXIT;
}
return 0;
}
int ScreenRecorder::initConvertedSamples(uint8_t*** converted_input_samples,
AVCodecContext* output_codec_context,
int frame_size) {
int error;
/* Allocate as many pointers as there are audio channels.
* Each pointer will later point to the audio samples of the corresponding
* channels (although it may be NULL for interleaved formats).
*/
if (!(*converted_input_samples = (uint8_t**)calloc(output_codec_context->channels,
sizeof(**converted_input_samples)))) {
fprintf(stderr, "Could not allocate converted input sample pointers\n");
return AVERROR(ENOMEM);
}
/* Allocate memory for the samples of all channels in one consecutive
* block for convenience. */
if (av_samples_alloc(*converted_input_samples, nullptr,
output_codec_context->channels,
frame_size,
output_codec_context->sample_fmt, 0) < 0) {
exit(1);
}
return 0;
}
static int64_t pts = 0;
void ScreenRecorder::captureAudio() {
int ret;
AVPacket* inPacket, * outPacket;
AVFrame* rawFrame, * scaledFrame;
uint8_t** resampledData;
init_fifo();
//allocate space for a packet
inPacket = (AVPacket*)av_malloc(sizeof(AVPacket));
if (!inPacket) {
cerr << "Cannot allocate an AVPacket for encoded video" << endl;
exit(1);
}
av_init_packet(inPacket);
//allocate space for a packet
rawFrame = av_frame_alloc();
if (!rawFrame) {
cerr << "Cannot allocate an AVPacket for encoded video" << endl;
exit(1);
}
scaledFrame = av_frame_alloc();
if (!scaledFrame) {
cerr << "Cannot allocate an AVPacket for encoded video" << endl;
exit(1);
}
outPacket = (AVPacket*)av_malloc(sizeof(AVPacket));
if (!outPacket) {
cerr << "Cannot allocate an AVPacket for encoded video" << endl;
exit(1);
}
//init the resampler
SwrContext* resampleContext = nullptr;
resampleContext = swr_alloc_set_opts(resampleContext,
av_get_default_channel_layout(outAudioCodecContext->channels),
outAudioCodecContext->sample_fmt,
outAudioCodecContext->sample_rate,
av_get_default_channel_layout(inAudioCodecContext->channels),
inAudioCodecContext->sample_fmt,
inAudioCodecContext->sample_rate,
0,
nullptr);
if (!resampleContext) {
cerr << "Cannot allocate the resample context" << endl;
exit(1);
}
if ((swr_init(resampleContext)) < 0) {
fprintf(stderr, "Could not open resample context\n");
swr_free(&resampleContext);
exit(1);
}
while (true) {
if (pauseCapture) {
cout << "Pause audio" << endl;
}
cv.wait(ul, [this]() { return !pauseCapture; });
if (stopCapture) {
break;
}
ul.unlock();
if (av_read_frame(inAudioFormatContext, inPacket) >= 0 && inPacket->stream_index == audioStreamIndx) {
//decode audio routing
av_packet_rescale_ts(outPacket, inAudioFormatContext->streams[audioStreamIndx]->time_base, inAudioCodecContext->time_base);
if ((ret = avcodec_send_packet(inAudioCodecContext, inPacket)) < 0) {
cout << "Cannot decode current audio packet " << ret << endl;
continue;
}
while (ret >= 0) {
ret = avcodec_receive_frame(inAudioCodecContext, rawFrame);
if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF)
break;
else if (ret < 0) {
cerr << "Error during decoding" << endl;
exit(1);
}
if (outAVFormatContext->streams[outAudioStreamIndex]->start_time <= 0) {
outAVFormatContext->streams[outAudioStreamIndex]->start_time = rawFrame->pts;
}
initConvertedSamples(&resampledData, outAudioCodecContext, rawFrame->nb_samples);
swr_convert(resampleContext,
resampledData, rawFrame->nb_samples,
(const uint8_t**)rawFrame->extended_data, rawFrame->nb_samp
add_samples_to_fifo(resampledData, rawFrame->nb_samples);
//raw frame ready
av_init_packet(outPacket);
outPacket->data = nullptr;
outPacket->size = 0;
const int frame_size = FFMAX(av_audio_fifo_size(fifo), outAudioCodecContext->frame_size);
scaledFrame = av_frame_alloc();
if (!scaledFrame) {
cerr << "Cannot allocate an AVPacket for encoded video" << endl;
exit(1);
}
scaledFrame->nb_samples = outAudioCodecContext->frame_size;
scaledFrame->channel_layout = outAudioCodecContext->channel_layout;
scaledFrame->format = outAudioCodecContext->sample_fmt;
scaledFrame->sample_rate = outAudioCodecContext->sample_rate;
av_frame_get_buffer(scaledFrame, 0);
while (av_audio_fifo_size(fifo) >= outAudioCodecContext->frame_size) {
ret = av_audio_fifo_read(fifo, (void**)(scaledFrame->data), outAudioCodecContext->frame_size);
scaledFrame->pts = pts;
pts += scaledFrame->nb_samples;
if (avcodec_send_frame(outAudioCodecContext, scaledFrame) < 0) {
cout << "Cannot encode current audio packet " << endl;
exit(1);
}
while (ret >= 0) {
ret = avcodec_receive_packet(outAudioCodecContext, outPacket);
if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF)
break;
else if (ret < 0) {
cerr << "Error during encoding" << endl;
exit(1);
}
av_packet_rescale_ts(outPacket, outAudioCodecContext->time_base, outAVFormatContext->streams[outAudioStreamIndex]->time_base);
outPacket->stream_index = outAudioStreamIndex;
write_lock.lock();
if (av_write_frame(outAVFormatContext, outPacket) != 0)
{
cerr << "Error in writing audio frame" << endl;
}
write_lock.unlock();
av_packet_unref(outPacket);
}
ret = 0;
}
av_frame_free(&scaledFrame);
av_packet_unref(outPacket);
}
}
}
}
int ScreenRecorder::captureVideoFrames() {
int64_t pts = 0;
int flag;
int frameFinished = 0;
bool endPause = false;
int numPause = 0;
ofstream outFile{ "..\\media\\log.txt", ios::out };
int frameIndex = 0;
value = 0;
pAVPacket = (AVPacket*)av_malloc(sizeof(AVPacket));
if (pAVPacket == nullptr) {
cerr << "Error in allocating AVPacket" << endl;
exit(-1);
}
pAVFrame = av_frame_alloc();
if (pAVFrame == nullptr) {
cerr << "Error: unable to alloc the AVFrame resources" << endl;
exit(-1);
}
outFrame = av_frame_alloc();
if (outFrame == nullptr) {
cerr << "Error: unable to alloc the AVFrame resources for out frame" << endl;
exit(-1);
}
int videoOutBuffSize;
int nBytes = av_image_get_buffer_size(outVideoCodecContext->pix_fmt, outVideoCodecContext->width, outVideoCodecContext->height, 32);
uint8_t* videoOutBuff = (uint8_t*)av_malloc(nBytes);
if (videoOutBuff == nullptr) {
cerr << "Error: unable to allocate memory" << endl;
exit(-1);
}
value = av_image_fill_arrays(outFrame->data, outFrame->linesize, videoOutBuff, AV_PIX_FMT_YUV420P, outVideoCodecContext->width, outVideoCodecContext->height, 1);
if (value < 0) {
cerr << "Error in filling image array" << endl;
}
SwsContext* swsCtx_;
if (avcodec_open2(pAVCodecContext, pAVCodec, nullptr) < 0) {
cerr << "Could not open codec" << endl;
exit(-1);
}
swsCtx_ = sws_getContext(pAVCodecContext->width, pAVCodecContext->height, pAVCodecContext->pix_fmt, outVideoCodecContext->width, outVideoCodecContext->height, outVideoCodecContext->pix_fmt, SWS_BICUBIC,
nullptr, nullptr, nullptr);
AVPacket outPacket;
int gotPicture;
time_t startTime;
time(&startTime);
while (true) {
if (pauseCapture) {
cout << "Pause" << endl;
outFile << "/////////////////// Pause ///////////////////" << endl;
cout << "outVideoCodecContext->time_base: " << outVideoCodecContext->time_base.num << ", " << outVideoCodecContext->time_base.den << endl;
}
cv.wait(ul, [this]() { return !pauseCapture; }); //pause capture (not busy waiting)
if (endPause) {
endPause = false;
}
if (stopCapture) //check if the capture has to stop
break;
ul.unlock();
if (av_read_frame(pAVFormatContext, pAVPacket) >= 0 && pAVPacket->stream_index == VideoStreamIndx) {
av_packet_rescale_ts(pAVPacket, pAVFormatContext->streams[VideoStreamIndx]->time_base, pAVCodecContext->time_base);
value = avcodec_decode_video2(pAVCodecContext, pAVFrame, &frameFinished, pAVPacket);
if (value < 0) {
cout << "Unable to decode video" << endl;
}
if (frameFinished) { //frame successfully decoded
//sws_scale(swsCtx_, pAVFrame->data, pAVFrame->linesize, 0, pAVCodecContext->height, outFrame->data, outFrame->linesize);
av_init_packet(&outPacket);
outPacket.data = nullptr;
outPacket.size = 0;
if (outAVFormatContext->streams[outVideoStreamIndex]->start_time <= 0) {
outAVFormatContext->streams[outVideoStreamIndex]->start_time = pAVFrame->pts;
}
//disable warning on the console
outFrame->width = outVideoCodecContext->width;
outFrame->height = outVideoCodecContext->height;
outFrame->format = outVideoCodecContext->pix_fmt;
sws_scale(swsCtx_, pAVFrame->data, pAVFrame->linesize, 0, pAVCodecContext->height, outFrame->data, outFrame->linesize);
avcodec_encode_video2(outVideoCodecContext, &outPacket, outFrame, &gotPicture);
if (gotPicture) {
if (outPacket.pts != AV_NOPTS_VALUE) {
outPacket.pts = av_rescale_q(outPacket.pts, videoSt->codec->time_base, videoSt->time_base);
}
if (outPacket.dts != AV_NOPTS_VALUE) {
outPacket.dts = av_rescale_q(outPacket.dts, videoSt->codec->time_base, videoSt->time_base);
}
//cout << "Write frame " << j++ << " (size = " << outPacket.size / 1000 << ")" << endl;
//cout << "(size = " << outPacket.size << ")" << endl;
//av_packet_rescale_ts(&outPacket, outVideoCodecContext->time_base, outAVFormatContext->streams[outVideoStreamIndex]->time_base);
//outPacket.stream_index = outVideoStreamIndex;
outFile << "outPacket->duration: " << outPacket.duration << ", " << "pAVPacket->duration: " << pAVPacket->duration << endl;
outFile << "outPacket->pts: " << outPacket.pts << ", " << "pAVPacket->pts: " << pAVPacket->pts << endl;
outFile << "outPacket.dts: " << outPacket.dts << ", " << "pAVPacket->dts: " << pAVPacket->dts << endl;
time_t timer;
double seconds;
mu.lock();
if (!activeMenu) {
time(&timer);
seconds = difftime(timer, startTime);
int h = (int)(seconds / 3600);
int m = (int)(seconds / 60) % 60;
int s = (int)(seconds) % 60;
std::cout << std::flush << "\r" << std::setw(2) << std::setfill('0') << h << ':'
<< std::setw(2) << std::setfill('0') << m << ':'
<< std::setw(2) << std::setfill('0') << s << std::flush;
}
mu.unlock();
write_lock.lock();
if (av_write_frame(outAVFormatContext, &outPacket) != 0) {
cerr << "Error in writing video frame" << endl;
}
write_lock.unlock();
av_packet_unref(&outPacket);
}
av_packet_unref(&outPacket);
av_free_packet(pAVPacket); //avoid memory saturation
}
}
}
outFile.close();
av_free(videoOutBuff);
return 0;
}
I resolved this problem performing an avformat_close_input(&inAudioFormatContext) before enter in pause, and an avformat_open_input(&inAudioFormatContext, "audio=Microfono (Realtek(R) Audio)", audioInputFormat, &audioOptions) after resume the recording. In this way the final file seems well syncronized with video.

Quectel EC25 Sending SMS and getting +CMS ERROR 305

This code sends some of SMS messages. But it gives error for some of the messages. It may about some wrong character that GSM module does not recognize like `(.
Is there any one can help to fix the code.
I am checking if GSM device is attached to ttyUSB2.
This is C++ code.
int sendSms(UsbPort &device, string phoneNumber, string message) {
char buf[MAXBUF] = {0};
int n;
if(device.fildes > 0) {
int max_check = 0;
if (write(device.fildes, "ATZ\r", 4) < 4) {
printf("ATZ write error - %s \n", strerror(errno));
return -1;
}
this_thread::sleep_for(chrono::seconds(1));
if (write(device.fildes, "AT+CMGF=1\r", 10) < 10) {
printf("AT+CMGF=1 write error - %s \n", strerror(errno));
return -1;
}
if (tcdrain(device.fildes) != 0) {
perror("tcdrain() error");
return -1;
}
this_thread::sleep_for(chrono::seconds(1));
bzero(buf, sizeof(buf));
read(device.fildes, buf, MAXBUF - 1);
cout << "Buffer-1 = " << buf << endl;
if (write(device.fildes, "ATE+CSMS=1\r", 11) < 11) {
printf("ATE+CSMS=1 write error - %s \n", strerror(errno));
return -1;
}
if (tcdrain(device.fildes) != 0) {
perror("tcdrain() error");
return -1;
}
this_thread::sleep_for(chrono::seconds(1));
bzero(buf, sizeof(buf));
if ((n = read(device.fildes, buf, MAXBUF - 1)) > -1) {
int length = strlen(buf);
cout << "length = " << length << endl;
buf[length] = '\0';
cout << "Buffer-2 = " << buf << endl;
if (strstr(buf, "+CSMS:") != NULL) { // Ready to send SMS
cout << "Can send SMS: " + string(buf) << endl;
// Send SMS
string data1 = "AT+CMGS=\"" + phoneNumber + "\"\r";
if (write(device.fildes, data1.c_str(), data1.length()) < data1.length()) {
printf("AT+CMGS write error - %s \n", strerror(errno));
return -1;
}
else {
this_thread::sleep_for(chrono::seconds(1));
string data2 = message + "\x1A";
if (write(device.fildes, data2.c_str(), data2.length()) < data2.length()) {
printf("ATE+CSMS=1 write error - %s \n", strerror(errno));
return -1;
}
if (tcdrain(device.fildes) != 0) {
perror("tcdrain() error");
return -1;
}
this_thread::sleep_for(chrono::seconds(1));
bzero(buf, sizeof(buf));
if ((n = read(device.fildes, buf, MAXBUF - 1)) > -1) {
int length = strlen(buf);
cout << "length = " << length << endl;
buf[length] = '\0';
cout << "Buffer-2 = " << buf << endl;
if (strstr(buf, "OK") != NULL) {
cout << message + " sent to : " + telNo + " successfully." << endl;
return 0;
}
}
else {
cout << message + " sent to : " + telNo + " unsuccessful!" << endl;
return -1;
}
}
}
else {
cout << "Error: buf = " + string(buf) << endl;
return -1;
}
}
}
return -1;
}
this is the example of which it cannot send sms.
The problem was not about ASCII characters, but about sending a message longer than it should be.
When we use Concatenated SMS it solved our problem. It Send Sms without problem.
AT+CGMF=1
AT+CSCS="GSM"
AT+CSMP=17,167,0,241
AT+CMGS="Number"
> Message <CTRL+Z>

CreateDC returns an error 1801

I need to receive screenshots from MS Mirror driver, but unexpectedly I noticed, that CreateDC() function returns NULL and GetLastError gives me Error#1801 ("The printer name is invalid")
extern "C" __declspec(dllexport) HDC InitDC() {
DWORD dwAttach = 0;
DEVMODE devmode;
// Make sure we have a display on this thread.
BOOL change = EnumDisplaySettings(NULL,
ENUM_CURRENT_SETTINGS,
&devmode);
LPCWSTR driverName = L"Microsoft Mirror Driver";
devmode.dmFields = DM_BITSPERPEL |
DM_PELSWIDTH |
DM_PELSHEIGHT |
DM_POSITION ;
devmode.dmSize = sizeof(DEVMODE);
devmode.dmDriverExtra = 0;
if (change)
{
// query all display devices in the system until we hit a primary
// display device. Using it get the width and height of the primary
// so we can use that for the mirror driver. Also enumerate the
// display devices installed on this machine untill we hit
// our favourate mirrored driver, then extract the device name string
// of the format '\\.\DISPLAY#'
DISPLAY_DEVICE dispDevice;
FillMemory(&dispDevice, sizeof(DISPLAY_DEVICE), 0);
dispDevice.cb = sizeof(DISPLAY_DEVICE);
LPCWSTR deviceName = NULL;
devmode.dmDeviceName[0] = '\0';
INT devNum = 0;
BOOL result;
DWORD cxPrimary = 0xFFFFFFFF;
DWORD cyPrimary = 0xFFFFFFFF;
// First enumerate for Primary display device:
while ((result = EnumDisplayDevices(NULL,
devNum,
&dispDevice,
0)) == TRUE)
{
wcout << "DriverName: " << dispDevice.DeviceString << endl;
wcout << "DevName: " << dispDevice.DeviceName << endl;
if (dispDevice.StateFlags & DISPLAY_DEVICE_PRIMARY_DEVICE)
{
// Primary device. Find out its dmPelsWidht and dmPelsHeight.
EnumDisplaySettings(dispDevice.DeviceName,
ENUM_CURRENT_SETTINGS,
&devmode);
cxPrimary = devmode.dmPelsWidth;
cyPrimary = devmode.dmPelsHeight;
wcout << "Selected Primary DevName (width, height): " << dispDevice.DeviceName << " (" << cxPrimary << "," << cyPrimary << ")" << endl << endl;
break;
}
devNum++;
}
// error check
if (!result)
{
wcout << "No " << driverName << " found " << endl;
exit(0);
}
if (cxPrimary == 0xffffffff || cyPrimary == 0xffffffff)
{
wcout << "cxPrimary or cyPrimary not valid" << endl;
exit(0);
}
// Enumerate again for the mirror driver:
devNum = 0;
while ((result = EnumDisplayDevices(NULL,
devNum,
&dispDevice,
0)) == TRUE)
{
LPCWSTR devString = dispDevice.DeviceString;
wcout << " devString: "<< devString << endl;
if (wcscmp(devString, driverName ) == 0) {
wcout << " Driver selected: "<< driverName << endl;
break;
}
devNum++;
}
// error check
if (!result)
{
wcout << "No " << driverName << " found " << endl;
exit(0);
}
wcout << "DevNum " << devNum << endl <<
"DeviceName: " << dispDevice.DeviceName << endl <<
"DeviceString: " << dispDevice.DeviceString << endl <<
"DeviceID: " << dispDevice.DeviceID << endl <<
"DeviceKey: " << dispDevice.DeviceKey << endl;
CHAR *deviceNum = new CHAR[MAX_PATH];
LPSTR deviceSub;
// Simply extract 'DEVICE#' from registry key. This will depend
// on how many mirrored devices your driver has and which ones
// you intend to use.
_wcsupr(&dispDevice.DeviceKey[0]);
deviceSub = (LPSTR)(wcsstr(&dispDevice.DeviceKey[0],
L"\\DEVICE"));
if (!deviceSub) {
printf("deviceSub - yes \n");
deviceNum[0] = (CHAR)(((string)("DEVICE0")).c_str());
}
else {
printf("!deviceSub \n");
deviceNum[0] = (CHAR)(((string)("DEVICE1")).c_str());
}
// Reset the devmode for mirror driver use:
FillMemory(&devmode, sizeof(DEVMODE), 0);
devmode.dmSize = sizeof(DEVMODE);
devmode.dmDriverExtra = 0;
devmode.dmFields = DM_BITSPERPEL |
DM_PELSWIDTH |
DM_PELSHEIGHT |
DM_POSITION;
//wcscpy( devmode.dmDeviceName, sizeof(devmode.dmDeviceName, L"mirror" );
deviceName = dispDevice.DeviceName;
StringCbCopy(devmode.dmDeviceName, sizeof(devmode.dmDeviceName), dispDevice.DeviceName);
wcout << "dmDeviceName: " << devmode.dmDeviceName << endl;
wcout << "deviceName: " << deviceName << endl;
wcout << "driverName: " << driverName << endl;
/* !!! THE PROBLEM IS HERE !!!*/
HDC hdc = CreateDC(driverName, deviceName, NULL, &devmode );
if ( hdc == NULL ) {
wcout << "CreateDC error: " << GetLastError() << endl;
return NULL;
}
return hdc;
}
return NULL;
}
Thanks for an assistance!
UPD1:
deviceName = "\\.\DISPLAYV1"
driverName = "Microsoft Mirror Driver"
devmode.dmDeviceName = "\\.\DISPLAYV1"

Can't send data to HID with libusb on windows

I'm currently trying to make a little piece of code that receive and send data to a HID (Texas Instrument HDK). There is no bug on the embedded system code (i can send data with a java program on mac OS to the device).
The reception is working but i can't send data (always getting error io return code).
Here's the code
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <iostream>
#include "libusb.h"
const static int PACKET_INT_LEN = 4;
const static int INTERFACE = 0;
const static int ENDPOINT_INT_IN = 0x83; /* endpoint 3 address for IN */
const static int ENDPOINT_INT_OUT = 0x04; /* endpoint 4 address for OUT */
const static int TIMEOUT = 5000;
#pragma comment(lib, "libusb-1.0.lib")
using namespace std;
libusb_device ** DoList();
libusb_device_handle * GetDevice(libusb_device ** deviceList);
int test_interrupt_transfer(libusb_device_handle * devh);
void error_interrupt_transfert(int r);
int main()
{
libusb_context ** context = NULL;
libusb_device_handle * deviceHandle = NULL;
int result_init = 0;
result_init = libusb_init(context);
if (result_init < 0)
cout << "Failed to init libusb." << endl;
else
deviceHandle = GetDevice(DoList());
int err = libusb_kernel_driver_active(deviceHandle, 0);
if (err >= LIBUSB_SUCCESS)
{
if (err == 1)
{
printf("Kernel driver is active, trying to detach");
err = libusb_detach_kernel_driver(deviceHandle, 0);
if (err != LIBUSB_SUCCESS)
{
printf("Error detaching interface from kernel");
}
}
}
if (libusb_kernel_driver_active(deviceHandle, 0) == 1)
{
if (libusb_detach_kernel_driver(deviceHandle, 0) == 0)
cout << "Kernel driver detatched !" << endl;
}
while (1)
{
test_interrupt_transfer(deviceHandle);
cout << 1 << endl;
Sleep(3000);
}
system("pause");
}
libusb_device ** DoList()
{
libusb_device **devs;
ssize_t count;
count = libusb_get_device_list(NULL, &devs);
if (count < 0)
{
cout << "Failed to get device list";
return NULL;
}
libusb_device *dev;
int i = 0;
cout << "Device list" << endl;
while ((dev = devs[i++]) != NULL)
{
struct libusb_device_descriptor desc;
int r = libusb_get_device_descriptor(dev, &desc);
if (r < 0)
{
cout << "Failed to get device descriptor" << endl;
return NULL;
}
printf("\t%04x:%04x (bus %d, device %d)\n",
desc.idVendor, desc.idProduct,
libusb_get_bus_number(dev), libusb_get_device_address(dev));
}
return devs;
}
libusb_device_handle * GetDevice(libusb_device ** devList)
{
int i = 0,
vid = 0x1cbe,
pid = 0;
libusb_device * dev;
libusb_device_handle * handle = NULL;
unsigned char strDesc[256];
if (devList == NULL)
{
return NULL;
}
while ((dev = devList[i++]) != NULL)
{
struct libusb_device_descriptor desc;
struct libusb_config_descriptor ** conDesc = NULL;
int ret = libusb_get_device_descriptor(dev, &desc);
if (ret < 0)
{
cout << "Failed libusb_get_device_descriptor" << endl;
continue;
}
if (desc.idVendor == vid && desc.idProduct == pid)
{
int ret = libusb_open(dev, &handle);
if (ret < 0)
{
cout << "Failed libusb_open" << ret << endl;
break;
}
ret = libusb_claim_interface(handle, 0);
if (ret < 0)
{
cout << "Failed libusb_claim_interface" << endl;
libusb_close(handle);
handle = NULL;
break;
}
libusb_get_string_descriptor_ascii(handle, desc.iManufacturer, strDesc, 256);
printf(" Manufacturer = %s\n", strDesc);
libusb_get_string_descriptor_ascii(handle, desc.iProduct, strDesc, 256);
printf(" Product = %s\n", strDesc);
libusb_get_string_descriptor_ascii(handle, desc.iSerialNumber, strDesc, 256);
printf(" Serial number = %s\n", strDesc);
break;
}
}
cout << "Success openning device" << endl;
libusb_free_device_list(devList, 1);
return handle;
}
int test_interrupt_transfer(libusb_device_handle * devh)
{
int r, i;
int transferred = 0;
int * ptransferred = &transferred;
unsigned char answer[PACKET_INT_LEN];
unsigned char question[2];
r = libusb_interrupt_transfer(devh, ENDPOINT_INT_OUT, question,
sizeof(question), ptransferred, TIMEOUT);
if (r < 0) {
error_interrupt_transfert(r);
return r;
}
r = libusb_interrupt_transfer(devh, ENDPOINT_INT_IN, answer, PACKET_INT_LEN,
&transferred, TIMEOUT);
if (r < 0)
{
error_interrupt_transfert(r);
return r;
}
for (i = 0; i < PACKET_INT_LEN; i++)
{
printf("%02x; ", answer[i]);
}
printf("\n");
return 0;
}
void error_interrupt_transfert(int r)
{
switch (r)
{
case LIBUSB_SUCCESS: cout << "Success" << endl;
break;
case LIBUSB_ERROR_TIMEOUT: cout << "Timeout" << endl;
break;
case LIBUSB_ERROR_PIPE: cout << "Error pipe" << endl;
break;
case LIBUSB_ERROR_OVERFLOW: cout << "Overflow" << endl;
break;
case LIBUSB_ERROR_NO_DEVICE: cout << "No device" << endl;
break;
case LIBUSB_ERROR_IO: cout << "Error IO" << endl;
break;
case LIBUSB_ERROR_NOT_FOUND: cout << "Not found" << endl;
break;
case LIBUSB_ERROR_INVALID_PARAM: cout << "Invalid param" << endl;
break;
case LIBUSB_ERROR_ACCESS: cout << "Error access" << endl;
break;
case LIBUSB_ERROR_INTERRUPTED: cout << "Interrupted" << endl;
break;
case LIBUSB_ERROR_BUSY: cout << "Busy" << endl;
break;
case LIBUSB_ERROR_NO_MEM: cout << "No memory" << endl;
break;
case LIBUSB_ERROR_NOT_SUPPORTED: cout << "Not supported" << endl;
break;
case LIBUSB_ERROR_OTHER: cout << "Other" << endl;
break;
default: cout << "Unknow error code" << r << endl;
}
}
Any idea folks?
Calmant Kévin

server freezes when handling large messages in simple server c++

I have a client and server running, and it seems to run great, until I either a really large message, or a partial message. In either of those events it freezes. The buffer is set to 1024, but changing it doesn't seem to affect the message at all. I've copied the getRequest function where it freezes below.
If anyone knows why it freezes or how to deal with large and partial messages, that would be great, thanks.
It freezes on the line int nread = (client, buf_,1024,0); Any solutions?
cout << "entered get request while loop" << endl;
int nread = recv(client,buf_,1024,0);
cout << "number read: " << nread << endl;
string
Server::get_request(int client) {
cout << "getting request" << endl;
string request = "";
// read until we get a newline
while (cache.find("\n") == string::npos) {
cout << "entered get request while loop" << endl;
int nread = recv(client,buf_,1024,0);
if (nread < 0) {
if (errno == EINTR)
// the socket call was interrupted -- try again
continue;
else
// an error occurred, so break out
return "";
} else if (nread == 0) {
// the socket is closed
return "";
}
// be sure to use append in case we have binary data
cache.append(buf_,nread);
cout << "cache: " << cache << " : " << endl;
}
int position = cache.find("\n");
if (position == -1){
request = cache;
cache = "";
}
else{
cout << "Cache position: " << position << endl;
request = cache.substr(0,position+1);
cache.erase(0,position+1);
}
cout << "request: " << request << " : " << endl;
return request;
}
This is the full server.cc file
#include "server.h"
#include <vector>
#include <map>
#include <sstream>
#include <iostream>
Server::Server(int port) {
// setup variables
port_ = port;
buflen_ = 1024;
buf_ = new char[buflen_+1];
// cache = "";
}
Server::~Server() {
delete[] buf_;
users.clear();
}
void
Server::run() {
// create and run the server
create();
serve();
}
void
Server::create() {
struct sockaddr_in server_addr;
// setup socket address structure
memset(&server_addr,0,sizeof(server_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(port_);
server_addr.sin_addr.s_addr = INADDR_ANY;
// create socket
server_ = socket(PF_INET,SOCK_STREAM,0);
if (!server_) {
perror("socket");
exit(-1);
}
// set socket to immediately reuse port when the application closes
int reuse = 1;
if (setsockopt(server_, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)) < 0) {
perror("setsockopt");
exit(-1);
}
// call bind to associate the socket with our local address and
// port
if (bind(server_,(const struct sockaddr *)&server_addr,sizeof(server_addr)) < 0) {
perror("bind");
exit(-1);
}
// convert the socket to listen for incoming connections
if (listen(server_,SOMAXCONN) < 0) {
perror("listen");
exit(-1);
}
}
void
Server::close_socket() {
close(server_);
}
void
Server::serve() {
// setup client
int client;
struct sockaddr_in client_addr;
socklen_t clientlen = sizeof(client_addr);
// accept clients
while ((client = accept(server_,(struct sockaddr *)&client_addr,&clientlen)) > 0) {
handle(client);
}
close_socket();
}
Server::Message Server::parse_request(string request){
stringstream ss;
istringstream istr(request);
Message message;
message.needed = false;
message.valid = true;
message.user = "";
message.index = -1;
// istream_iterator<string> be
istr >> message.command;
//message.command = ss.str();
cout << "got command:" << message.command << ":" << endl;
if(message.command == "put")
{
istr >> message.user;
//ss << istr;
istr >> message.subject;
istr >> message.length;
cout << "message.length = " << message.length <<endl;
message.needed = false;
}
else if (message.command == "list"){
istr >> message.user;
message.needed = false;
message.length = 0;
}
else if (message.command == "get"){
istr >> message.user;
istr >> message.index;
message.needed = false;
message.length = 0;
}
else if (message.command == "reset"){
message.needed = false;
message.length = 0;
}
else{
cout << "I don't recognize that request.";
message.valid = false;
}
return message;
}
void Server::get_value(int client, Message message){
//call recv until all bytes needed are recieved
while(message.needed){
int nread = recv(client,buf_,1024,0);
if (nread < 0) {
if (errno == EINTR)
// the socket call was interrupted -- try again
continue;
else
// an error occurred, so break out
return;
} else if (nread == 0) {
// the socket is closed
return;
}
cache.append(buf_,nread);
cout << "cache length " << cache.size();
if(message.length <= cache.size()){
cout << "Message value " << message.value;
cout << "cache length " << cache.size();
message.needed = false;
message.value = cache.substr(0,message.length);
cache.erase(0,message.length);
cout << "Message value " << message.value;
cout << "cache length " << cache.size();
}
}
}
string
Server::get_request(int client) {
cout << "getting request" << endl;
string request = "";
// read until we get a newline
while (cache.find("\n") == string::npos) {
cout << "entered get request while loop" << endl;
int nread = recv(client,buf_,1024,0);
if (nread < 0) {
if (errno == EINTR)
// the socket call was interrupted -- try again
continue;
else
// an error occurred, so break out
return "";
} else if (nread == 0) {
// the socket is closed
return "";
}
// be sure to use append in case we have binary data
cache.append(buf_,nread);
cout << "cache: " << cache << " : " << endl;
}
int position = cache.find("\n");
// int position = 0;
// while (cache.find("/n") == string::npos)
// {
// position++;
// }
if (position == -1){
request = cache;
cache = "";
}
else{
cout << "Cache position: " << position << endl;
request = cache.substr(0,position+1);
cache.erase(0,position+1);
}
cout << "request: " << request << " : " << endl;
// a better server would cut off anything after the newline and
// save it in a cache
return request;
}
bool Server::send_response(int client, string response) {
// prepare to send response
cout << "sending response:" << response << ":" << endl;
const char* ptr = response.c_str();
int nleft = response.length();
int nwritten;
// loop to be sure it is all sent
while (nleft) {
if ((nwritten = send(client, ptr, nleft, 0)) < 0) {
if (errno == EINTR) {
// the socket call was interrupted -- try again
continue;
} else {
// an error occurred, so break out
perror("write");
return false;
}
} else if (nwritten == 0) {
// the socket is closed
return false;
}
nleft -= nwritten;
ptr += nwritten;
cout << "number written: " << nwritten << endl;
}
cout << "finished sending response " << endl;
return true;
}
bool Server::handle_response(int client, Message message) {
cout << "handling response" << endl;
bool success = false;
if(message.command == "put"){
if(message.length == 0){
return false;
}
message.value = cache.substr(0,message.length);
cache.erase(0,message.length);
if(subjects.count(message.user) == 0){
vector<string> userSubjects;
subjects[message.user] = userSubjects;
}
subjects[message.user].push_back(message.subject);
if(users.count(message.user) == 0){
vector<Message> messages;
users[message.user] = messages;
}
users[message.user].push_back(message);
// users.insert(message.user, message.subject);
cout << "sending response to client" << endl;
success = send_response(client, "OK\n");
}
else if("list" == message.command){
if(message.user == ""){
return false;
}
vector<string> currentSubjects = subjects[message.user];
cout << "subjects for message.user: " << message.user << endl;
stringstream sstream;
sstream << "list " << currentSubjects.size() << "\n";
//success = send_response(client, sstream.str());
// if(success == false){
// return false;
// }
// cout << "client sent user" << endl;
for (int i=0; i<currentSubjects.size(); i++){
// stringstream sstm;
sstream << (i+1) << " " << currentSubjects[i] << "\n";
}
success = send_response(client, sstream.str());
if(success == false){
return false;
}
// success = true;
cout << "message list sent successfully" << endl;
}
else if (message.command == "get"){
if(message.index == -1){
return false;
}
if(message.user == ""){
return false;
}
vector<Message> currentMessages = users[message.user];
if(message.index > currentMessages.size()){
return false;
}
stringstream sstm;
for (int i=0; i<currentMessages.size(); i++){
if ((i+1) == message.index){
sstm << "message " << currentMessages[i].subject << " " << currentMessages[i].length << "\n" << currentMessages[i].value;
cout << "message.value = " << currentMessages[i].value << endl;
}
}
cout << "message to send " << sstm.str() << endl;
success = send_response(client, sstm.str());
if(success == false){
return false;
}
// success = true;
}
else if (message.command == "reset"){
users.clear();
subjects.clear();
success = send_response(client, "OK\n");
// success = true;
}
else {
debug = true;
if (debug == true){
cout << "Debug message: " << "No valid command found in handle" << endl;
}
}
return success;
}
void
Server::handle(int client) {
// loop to handle all requests
while (1) {
// get a request
cout << "looking for new request" << endl;
string request = get_request(client);
cout << "request = " << request << endl;
// break if client is done or an error occurred
if (request.empty()) {
cout << "empty request" << endl;
break;
}
cout << "request:" << request << ":" << endl;
//parse
Message message = parse_request(request);
cout << "finished parsing" << endl;
if(message.valid == false){
cout << "invalid message" << endl;
send_response(client, "error unrecognized command\n");
cout << "cache after break from bad command: " << cache << endl;
continue;
}
if(message.length > cache.size()){
message.needed = true;
cout << "message length greater than cache size" << endl;
cout << "cache.size = " << cache.size() << endl;
}
if(message.needed){
get_value(client, message);
}
// handle message
bool success = handle_response(client, message);
cout << "finished handling response" << endl;
cout << "cache after handle: " << cache << " : " << endl;
// break if an error occurred
if (!success) {
cout << "error handling request" << endl;
send_response(client, "error handling request\n");
continue;
}
cout << "end of request" << endl;
}
close(client);
}