Related
I am trying to have a raspberry pi controll the status of GPIO pins which are connected to a relay board for a christmas light display, the issue is that the pins are stuck in the on position and i get the error "Unhandled Event 10" pretty often
Here is the code that controlls the pins based on midi playback.
#include <alsa/asoundlib.h>
#include <wiringPi.h>
#include <limits.h>
#include <unistd.h>
#include <math.h>
static snd_seq_t *seq_handle;
static int in_port;
//16 melody channels, using wiringPi numbering
int pinMapping[] = {
0, //0
1, //1
2, //2
3, //3
4, //4
5, //5
6, //6
21, //7
22, //8
26, //9
23, //10
24, //11
27, //12
25, //13
28, //14
29, //15
};
#define TOTAL_PINS sizeof(pinMapping) / sizeof(int)
#define THRUPORTCLIENT 14
#define THRUPORTPORT 0
void midi_open(void)
{
snd_seq_open(&seq_handle, "default", SND_SEQ_OPEN_INPUT, 0);
snd_seq_set_client_name(seq_handle, "LightOrgan");
in_port = snd_seq_create_simple_port(seq_handle, "listen:in",
SND_SEQ_PORT_CAP_WRITE|SND_SEQ_PORT_CAP_SUBS_WRITE,
SND_SEQ_PORT_TYPE_APPLICATION);
if( snd_seq_connect_from(seq_handle, in_port, THRUPORTCLIENT, THRUPORTPORT) == -1) {
perror("Can't connect to thru port");
exit(-1);
}
}
snd_seq_event_t *midi_read(void)
{
snd_seq_event_t *ev = NULL;
snd_seq_event_input(seq_handle, &ev);
return ev;
}
//Currently playing note, by pin
int pinNotes[TOTAL_PINS];
//Currently playing channel, by pin
int pinChannels[TOTAL_PINS];
//Enabled channels
int playChannels[16];
void clearPinNotes() {
int i;
for(i=0; i< TOTAL_PINS; i++) {
pinNotes[i] = -1;
}
}
void myDigitalWrite(int pinIdx, int val) {
val ? printf("%i (%i) ON\n", pinIdx, pinMapping[pinIdx]) : printf("%i (%i) OFF\n", pinIdx, pinMapping[pinIdx]);
digitalWrite( pinMapping[pinIdx], val );
}
void clearPinChannels() {
int i;
for(i=0; i< TOTAL_PINS; i++) {
pinChannels[i] = INT_MAX;
}
}
void clearPinsState() {
clearPinNotes();
clearPinChannels();
}
void pinsOn() {
int i;
for(i=0; i< TOTAL_PINS; i++) {
myDigitalWrite(i, 1);
}
}
void pinsOff() {
int i;
for(i=0; i< TOTAL_PINS; i++) {
myDigitalWrite(i, 1);
}
}
void setChannelInstrument(int channel, int instr) {
printf("setting channel %i to instrument %i\n", channel, instr);
playChannels[channel] = instr;
}
int isPercussion(int instrVal) {
return instrVal >= 8 && instrVal <= 15;
}
int isPercussionChannel(int channel) {
int instr = playChannels[channel];
return isPercussion(instr);
}
int isBase(int instrVal) {
return instrVal >= 32 && instrVal <= 39;
}
int isSynth(int instrVal) {
return instrVal >= 88 && instrVal <= 103;
}
int choosePinIdx(int note, int channel) {
//Return the note modulated by the number of melody pins
int val = note % (TOTAL_PINS * 2);
return val / 2;
}
void midi_process(snd_seq_event_t *ev)
{
//If this event is a PGMCHANGE type, it's a request to map a channel to an instrument
if( ev->type == SND_SEQ_EVENT_PGMCHANGE ) {
//printf("PGMCHANGE: channel %2d, %5d, %5d\n", ev->data.control.channel, ev->data.control.param, ev->data.control.value);
//Clear pins state, this is probably the beginning of a new song
clearPinsState();
setChannelInstrument(ev->data.control.channel, ev->data.control.value);
}
//Note on/off event
else if ( ((ev->type == SND_SEQ_EVENT_NOTEON)||(ev->type == SND_SEQ_EVENT_NOTEOFF)) ) {
//choose the output pin based on the pitch of the note
int pinIdx = choosePinIdx(ev->data.note.note, ev->data.note.channel);
if(!isPercussionChannel(ev->data.note.channel) ) {
int isOn = 1;
//Note velocity == 0 means the same thing as a NOTEOFF type event
if( ev->data.note.velocity == 0 || ev->type == SND_SEQ_EVENT_NOTEOFF) {
isOn = 0;
}
//If pin is set to be turned on
if( isOn ) {
//If pin is currently available to play a note, or if currently playing channel can be overriden due to higher priority channel
if( pinNotes[pinIdx] == -1 || pinChannels[pinIdx] > ev->data.note.channel ) {
if( (pinChannels[pinIdx] > ev->data.note.channel ) && pinNotes[pinIdx] != -1) {
//printf("OVERRIDING CHANNEL %i for %i\n", pinChannels[pinIdx], ev->data.note.channel);
}
//Write to the pin, save the note to pinNotes
//printf("Pin %i - %s %i %i \n", pinIdx, isOn ? "on" : "off", ev->data.note.note, ev->data.note.channel);
myDigitalWrite(pinIdx, 1);
pinNotes[pinIdx] = ev->data.note.note;
pinChannels[pinIdx] = ev->data.note.channel;
}
}
//Pin is to be turned off
else {
//If this is the note that turned the pin on..
if( pinNotes[pinIdx] == ev->data.note.note && pinChannels[pinIdx] == ev->data.note.channel ) {
//Write to the pin, indicate that pin is available
//printf("Pin %i - %s %i %i \n", pinIdx, isOn ? "on" : "off", ev->data.note.note, ev->data.note.channel);
myDigitalWrite(pinIdx, 0);
pinNotes[pinIdx] = -1;
pinChannels[pinIdx] = INT_MAX;
}
}
}
}
else {
printf("Unhandled event %2d\n", ev->type);
}
snd_seq_free_event(ev);
}
int main()
{
//Setup wiringPi
if( wiringPiSetup() == -1) {
exit(1);
}
//Setup all the pins to use OUTPUT mode
int i=0;
for(i=0; i< TOTAL_PINS; i++) {
pinMode( pinMapping[i], OUTPUT);
}
clearPinsState();
//Open a midi port, connect to thru port also
midi_open();
//Process events forever
while (1) {
midi_process(midi_read());
}
return -1;
}
I was hoping that the pins would trun on and off with the music but the pins appear to be stuck on.
I would like to test libvpx (vp9) temporal svc. For that matter I take examples/vpx_temporal_svc_encoder.c and modify it to add a decoder. If I take for example mode 3 with 3 temporal layers and 6 frame period and try to decode only layer 0 or layers 0 and 1 I get an error: "Failed to decode frame.: Corrupt frame detected. Failed to decode tile data". What am I missing ? Here is my code (had to remove unmodified part due to post limits):
/*
* Copyright (c) 2012 The WebM project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
// This is an example demonstrating how to implement a multi-layer VPx
// encoding scheme based on temporal scalability for video applications
// that benefit from a scalable bitstream.
#include <assert.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "./vpx_config.h"
#include "./y4minput.h"
#include "../vpx_ports/vpx_timer.h"
#include "vpx/vp8cx.h"
#include "vpx/vpx_encoder.h"
#include "vpx_ports/bitops.h"
#include "../tools_common.h"
#include "../video_writer.h"
#include "vpx/vpx_decoder.h"
#define ROI_MAP 0
#define zero(Dest) memset(&(Dest), 0, sizeof(Dest));
static const char *exec_name;
void usage_exit(void) { exit(EXIT_FAILURE); }
// Denoiser states for vp8, for temporal denoising.
enum denoiserStateVp8 {
kVp8DenoiserOff,
kVp8DenoiserOnYOnly,
kVp8DenoiserOnYUV,
kVp8DenoiserOnYUVAggressive,
kVp8DenoiserOnAdaptive
};
// Denoiser states for vp9, for temporal denoising.
enum denoiserStateVp9 {
kVp9DenoiserOff,
kVp9DenoiserOnYOnly,
// For SVC: denoise the top two spatial layers.
kVp9DenoiserOnYTwoSpatialLayers
};
static int mode_to_num_layers[13] = { 1, 2, 2, 3, 3, 3, 3, 5, 2, 3, 3, 3, 3 };
int main(int argc, char **argv) {
VpxVideoWriter *outfile[VPX_TS_MAX_LAYERS] = { NULL };
vpx_codec_ctx_t codec;
vpx_codec_enc_cfg_t cfg;
int frame_cnt = 0;
vpx_image_t raw;
vpx_codec_err_t res;
unsigned int width;
unsigned int height;
uint32_t error_resilient = 0;
int speed;
int frame_avail;
int got_data;
int flags = 0;
unsigned int i;
int pts = 0; // PTS starts at 0.
int frame_duration = 1; // 1 timebase tick per frame.
int layering_mode = 0;
int layer_flags[VPX_TS_MAX_PERIODICITY] = { 0 };
int flag_periodicity = 1;
#if ROI_MAP
vpx_roi_map_t roi;
#endif
vpx_svc_layer_id_t layer_id;
const VpxInterface *encoder = NULL;
struct VpxInputContext input_ctx;
struct RateControlMetrics rc;
int64_t cx_time = 0;
const int min_args_base = 13;
#if CONFIG_VP9_HIGHBITDEPTH
vpx_bit_depth_t bit_depth = VPX_BITS_8;
int input_bit_depth = 8;
const int min_args = min_args_base + 1;
#else
const int min_args = min_args_base;
#endif // CONFIG_VP9_HIGHBITDEPTH
double sum_bitrate = 0.0;
double sum_bitrate2 = 0.0;
double framerate = 30.0;
zero(rc.layer_target_bitrate);
memset(&layer_id, 0, sizeof(vpx_svc_layer_id_t));
memset(&input_ctx, 0, sizeof(input_ctx));
/* Setup default input stream settings */
input_ctx.framerate.numerator = 30;
input_ctx.framerate.denominator = 1;
input_ctx.only_i420 = 1;
input_ctx.bit_depth = 0;
exec_name = argv[0];
// Check usage and arguments.
if (argc < min_args) {
#if CONFIG_VP9_HIGHBITDEPTH
die("Usage: %s <infile> <outfile> <codec_type(vp8/vp9)> <width> <height> "
"<rate_num> <rate_den> <speed> <frame_drop_threshold> "
"<error_resilient> <threads> <mode> "
"<Rate_0> ... <Rate_nlayers-1> <bit-depth> \n",
argv[0]);
#else
//./vpx_temporal_svc_encoder ../9.yuv svc vp9 256 256 1 25 9 0 0 1 3 500000 500000 50000
die("Usage: %s <infile> <outfile> <codec_type(vp8/vp9)> <width> <height> "
"<rate_num> <rate_den> <speed> <frame_drop_threshold> "
"<error_resilient> <threads> <mode> "
"<Rate_0> ... <Rate_nlayers-1> \n",
argv[0]);
#endif // CONFIG_VP9_HIGHBITDEPTH
}
encoder = get_vpx_encoder_by_name(argv[3]);
if (!encoder) die("Unsupported codec.");
printf("Using %s\n", vpx_codec_iface_name(encoder->codec_interface()));
width = (unsigned int)strtoul(argv[4], NULL, 0);
height = (unsigned int)strtoul(argv[5], NULL, 0);
if (width < 16 || width % 2 || height < 16 || height % 2) {
die("Invalid resolution: %d x %d", width, height);
}
layering_mode = (int)strtol(argv[12], NULL, 0);
if (layering_mode < 0 || layering_mode > 13) {
die("Invalid layering mode (0..12) %s", argv[12]);
}
if (argc != min_args + mode_to_num_layers[layering_mode]) {
die("Invalid number of arguments");
}
input_ctx.filename = argv[1];
open_input_file(&input_ctx);
#if CONFIG_VP9_HIGHBITDEPTH
switch (strtol(argv[argc - 1], NULL, 0)) {
case 8:
bit_depth = VPX_BITS_8;
input_bit_depth = 8;
break;
case 10:
bit_depth = VPX_BITS_10;
input_bit_depth = 10;
break;
case 12:
bit_depth = VPX_BITS_12;
input_bit_depth = 12;
break;
default: die("Invalid bit depth (8, 10, 12) %s", argv[argc - 1]);
}
// Y4M reader has its own allocation.
if (input_ctx.file_type != FILE_TYPE_Y4M) {
if (!vpx_img_alloc(
&raw,
bit_depth == VPX_BITS_8 ? VPX_IMG_FMT_I420 : VPX_IMG_FMT_I42016,
width, height, 32)) {
die("Failed to allocate image", width, height);
}
}
#else
// Y4M reader has its own allocation.
if (input_ctx.file_type != FILE_TYPE_Y4M) {
if (!vpx_img_alloc(&raw, VPX_IMG_FMT_I420, width, height, 32)) {
die("Failed to allocate image", width, height);
}
}
#endif // CONFIG_VP9_HIGHBITDEPTH
// Populate encoder configuration.
res = vpx_codec_enc_config_default(encoder->codec_interface(), &cfg, 0);
if (res) {
printf("Failed to get config: %s\n", vpx_codec_err_to_string(res));
return EXIT_FAILURE;
}
// Update the default configuration with our settings.
cfg.g_w = width;
cfg.g_h = height;
#if CONFIG_VP9_HIGHBITDEPTH
if (bit_depth != VPX_BITS_8) {
cfg.g_bit_depth = bit_depth;
cfg.g_input_bit_depth = input_bit_depth;
cfg.g_profile = 2;
}
#endif // CONFIG_VP9_HIGHBITDEPTH
// Timebase format e.g. 30fps: numerator=1, demoninator = 30.
cfg.g_timebase.num = (int)strtol(argv[6], NULL, 0);
cfg.g_timebase.den = (int)strtol(argv[7], NULL, 0);
speed = (int)strtol(argv[8], NULL, 0);
if (speed < 0) {
die("Invalid speed setting: must be positive");
}
if (strncmp(encoder->name, "vp9", 3) == 0 && speed > 9) {
warn("Mapping speed %d to speed 9.\n", speed);
}
for (i = min_args_base;
(int)i < min_args_base + mode_to_num_layers[layering_mode]; ++i) {
rc.layer_target_bitrate[i - 13] = (int)strtol(argv[i], NULL, 0);
if (strncmp(encoder->name, "vp8", 3) == 0)
cfg.ts_target_bitrate[i - 13] = rc.layer_target_bitrate[i - 13];
else if (strncmp(encoder->name, "vp9", 3) == 0)
cfg.layer_target_bitrate[i - 13] = rc.layer_target_bitrate[i - 13];
}
// Real time parameters.
cfg.rc_dropframe_thresh = (unsigned int)strtoul(argv[9], NULL, 0);
cfg.rc_end_usage = VPX_CBR;
cfg.rc_min_quantizer = 2;
cfg.rc_max_quantizer = 56;
if (strncmp(encoder->name, "vp9", 3) == 0) cfg.rc_max_quantizer = 52;
cfg.rc_undershoot_pct = 50;
cfg.rc_overshoot_pct = 50;
cfg.rc_buf_initial_sz = 600;
cfg.rc_buf_optimal_sz = 600;
cfg.rc_buf_sz = 1000;
// Disable dynamic resizing by default.
cfg.rc_resize_allowed = 0;
// Use 1 thread as default.
cfg.g_threads = (unsigned int)strtoul(argv[11], NULL, 0);
error_resilient = (uint32_t)strtoul(argv[10], NULL, 0);
if (error_resilient != 0 && error_resilient != 1) {
die("Invalid value for error resilient (0, 1): %d.", error_resilient);
}
// Enable error resilient mode.
cfg.g_error_resilient = error_resilient;
cfg.g_lag_in_frames = 0;
cfg.kf_mode = VPX_KF_AUTO;
// Disable automatic keyframe placement.
cfg.kf_min_dist = cfg.kf_max_dist = 3000;
cfg.temporal_layering_mode = VP9E_TEMPORAL_LAYERING_MODE_BYPASS;
set_temporal_layer_pattern(layering_mode, &cfg, layer_flags,
&flag_periodicity);
set_rate_control_metrics(&rc, &cfg);
if (input_ctx.file_type == FILE_TYPE_Y4M) {
if (input_ctx.width != cfg.g_w || input_ctx.height != cfg.g_h) {
die("Incorrect width or height: %d x %d", cfg.g_w, cfg.g_h);
}
if (input_ctx.framerate.numerator != cfg.g_timebase.den ||
input_ctx.framerate.denominator != cfg.g_timebase.num) {
die("Incorrect framerate: numerator %d denominator %d",
cfg.g_timebase.num, cfg.g_timebase.den);
}
}
framerate = cfg.g_timebase.den / cfg.g_timebase.num;
// Open an output file for each stream.
for (i = 0; i < cfg.ts_number_layers; ++i) {
char file_name[PATH_MAX];
VpxVideoInfo info;
info.codec_fourcc = encoder->fourcc;
info.frame_width = cfg.g_w;
info.frame_height = cfg.g_h;
info.time_base.numerator = cfg.g_timebase.num;
info.time_base.denominator = cfg.g_timebase.den;
snprintf(file_name, sizeof(file_name), "%s_%d.ivf", argv[2], i);
outfile[i] = vpx_video_writer_open(file_name, kContainerIVF, &info);
if (!outfile[i]) die("Failed to open %s for writing", file_name);
assert(outfile[i] != NULL);
}
// No spatial layers in this encoder.
cfg.ss_number_layers = 1;
// Initialize codec.
#if CONFIG_VP9_HIGHBITDEPTH
if (vpx_codec_enc_init(
&codec, encoder->codec_interface(), &cfg,
bit_depth == VPX_BITS_8 ? 0 : VPX_CODEC_USE_HIGHBITDEPTH))
#else
if (vpx_codec_enc_init(&codec, encoder->codec_interface(), &cfg, 0))
#endif // CONFIG_VP9_HIGHBITDEPTH
die("Failed to initialize encoder");
if (strncmp(encoder->name, "vp8", 3) == 0) {
vpx_codec_control(&codec, VP8E_SET_CPUUSED, -speed);
vpx_codec_control(&codec, VP8E_SET_NOISE_SENSITIVITY, kVp8DenoiserOff);
vpx_codec_control(&codec, VP8E_SET_STATIC_THRESHOLD, 1);
vpx_codec_control(&codec, VP8E_SET_GF_CBR_BOOST_PCT, 0);
#if ROI_MAP
set_roi_map(encoder->name, &cfg, &roi);
if (vpx_codec_control(&codec, VP8E_SET_ROI_MAP, &roi))
die_codec(&codec, "Failed to set ROI map");
#endif
} else if (strncmp(encoder->name, "vp9", 3) == 0) {
vpx_svc_extra_cfg_t svc_params;
memset(&svc_params, 0, sizeof(svc_params));
vpx_codec_control(&codec, VP9E_SET_POSTENCODE_DROP, 0);
vpx_codec_control(&codec, VP9E_SET_DISABLE_OVERSHOOT_MAXQ_CBR, 0);
vpx_codec_control(&codec, VP8E_SET_CPUUSED, speed);
vpx_codec_control(&codec, VP9E_SET_AQ_MODE, 3);
vpx_codec_control(&codec, VP9E_SET_GF_CBR_BOOST_PCT, 0);
vpx_codec_control(&codec, VP9E_SET_FRAME_PARALLEL_DECODING, 0);
vpx_codec_control(&codec, VP9E_SET_FRAME_PERIODIC_BOOST, 0);
vpx_codec_control(&codec, VP9E_SET_NOISE_SENSITIVITY, kVp9DenoiserOff);
vpx_codec_control(&codec, VP8E_SET_STATIC_THRESHOLD, 1);
vpx_codec_control(&codec, VP9E_SET_TUNE_CONTENT, 0);
vpx_codec_control(&codec, VP9E_SET_TILE_COLUMNS, get_msb(cfg.g_threads));
vpx_codec_control(&codec, VP9E_SET_DISABLE_LOOPFILTER, 0);
#if ROI_MAP
set_roi_map(encoder->name, &cfg, &roi);
if (vpx_codec_control(&codec, VP9E_SET_ROI_MAP, &roi))
die_codec(&codec, "Failed to set ROI map");
vpx_codec_control(&codec, VP9E_SET_AQ_MODE, 0);
#endif
if (cfg.g_threads > 1)
vpx_codec_control(&codec, VP9E_SET_ROW_MT, 1);
else
vpx_codec_control(&codec, VP9E_SET_ROW_MT, 0);
if (vpx_codec_control(&codec, VP9E_SET_SVC, layering_mode > 0 ? 1 : 0))
die_codec(&codec, "Failed to set SVC");
for (i = 0; i < cfg.ts_number_layers; ++i) {
svc_params.max_quantizers[i] = cfg.rc_max_quantizer;
svc_params.min_quantizers[i] = cfg.rc_min_quantizer;
}
svc_params.scaling_factor_num[0] = cfg.g_h;
svc_params.scaling_factor_den[0] = cfg.g_h;
vpx_codec_control(&codec, VP9E_SET_SVC_PARAMETERS, &svc_params);
}
if (strncmp(encoder->name, "vp8", 3) == 0) {
vpx_codec_control(&codec, VP8E_SET_SCREEN_CONTENT_MODE, 0);
}
vpx_codec_control(&codec, VP8E_SET_TOKEN_PARTITIONS, 1);
// This controls the maximum target size of the key frame.
// For generating smaller key frames, use a smaller max_intra_size_pct
// value, like 100 or 200.
{
const int max_intra_size_pct = 1000;
vpx_codec_control(&codec, VP8E_SET_MAX_INTRA_BITRATE_PCT,
max_intra_size_pct);
}
const VpxInterface *decoder = NULL;
decoder = get_vpx_decoder_by_name( "vp9" );
if (!decoder) die("Unsupported codec.");
vpx_codec_ctx_t codec_dec;
vpx_codec_dec_cfg_t cfg_dec;
cfg_dec.w = width;
cfg_dec.h = height;
cfg_dec.threads = 1;
if (vpx_codec_dec_init( &codec_dec, decoder->codec_interface(), &cfg_dec, 0))
die_codec( &codec_dec, "Failed to initialize decoder.");
if(!codec.iface)
die_codec( &codec_dec, "vvv no iface" );
vpx_image_t *img_dec;
frame_avail = 1;
while (frame_avail || got_data) {
struct vpx_usec_timer timer;
vpx_codec_iter_t iter = NULL;
const vpx_codec_cx_pkt_t *pkt;
// Update the temporal layer_id. No spatial layers in this test.
layer_id.spatial_layer_id = 0;
layer_id.temporal_layer_id =
cfg.ts_layer_id[frame_cnt % cfg.ts_periodicity];
layer_id.temporal_layer_id_per_spatial[0] = layer_id.temporal_layer_id;
if (strncmp(encoder->name, "vp9", 3) == 0) {
vpx_codec_control(&codec, VP9E_SET_SVC_LAYER_ID, &layer_id);
} else if (strncmp(encoder->name, "vp8", 3) == 0) {
vpx_codec_control(&codec, VP8E_SET_TEMPORAL_LAYER_ID,
layer_id.temporal_layer_id);
}
flags = layer_flags[frame_cnt % flag_periodicity];
if (layering_mode == 0) flags = 0;
frame_avail = read_frame(&input_ctx, &raw);
if (frame_avail) ++rc.layer_input_frames[layer_id.temporal_layer_id];
vpx_usec_timer_start(&timer);
if (vpx_codec_encode(&codec, frame_avail ? &raw : NULL, pts, 1, flags,
VPX_DL_REALTIME)) {
die_codec(&codec, "Failed to encode frame");
}
vpx_usec_timer_mark(&timer);
cx_time += vpx_usec_timer_elapsed(&timer);
// Reset KF flag.
if (layering_mode != 7) {
layer_flags[0] &= ~VPX_EFLAG_FORCE_KF;
}
got_data = 0;
while ((pkt = vpx_codec_get_cx_data(&codec, &iter))) {
got_data = 1;
switch (pkt->kind) {
case VPX_CODEC_CX_FRAME_PKT:
for (i = cfg.ts_layer_id[frame_cnt % cfg.ts_periodicity];
i < cfg.ts_number_layers; ++i) {
vpx_video_writer_write_frame(outfile[i], pkt->data.frame.buf,
pkt->data.frame.sz, pts);
++rc.layer_tot_enc_frames[i];
rc.layer_encoding_bitrate[i] += 8.0 * pkt->data.frame.sz;
// Keep count of rate control stats per layer (for non-key frames).
if (i == cfg.ts_layer_id[frame_cnt % cfg.ts_periodicity] &&
!(pkt->data.frame.flags & VPX_FRAME_IS_KEY)) {
rc.layer_avg_frame_size[i] += 8.0 * pkt->data.frame.sz;
rc.layer_avg_rate_mismatch[i] +=
fabs(8.0 * pkt->data.frame.sz - rc.layer_pfb[i]) /
rc.layer_pfb[i];
++rc.layer_enc_frames[i];
}
}
// Update for short-time encoding bitrate states, for moving window
// of size rc->window, shifted by rc->window / 2.
// Ignore first window segment, due to key frame.
if (rc.window_size == 0) rc.window_size = 15;
if (frame_cnt > rc.window_size) {
sum_bitrate += 0.001 * 8.0 * pkt->data.frame.sz * framerate;
if (frame_cnt % rc.window_size == 0) {
rc.window_count += 1;
rc.avg_st_encoding_bitrate += sum_bitrate / rc.window_size;
rc.variance_st_encoding_bitrate +=
(sum_bitrate / rc.window_size) *
(sum_bitrate / rc.window_size);
sum_bitrate = 0.0;
}
}
// Second shifted window.
if (frame_cnt > rc.window_size + rc.window_size / 2) {
sum_bitrate2 += 0.001 * 8.0 * pkt->data.frame.sz * framerate;
if (frame_cnt > 2 * rc.window_size &&
frame_cnt % rc.window_size == 0) {
rc.window_count += 1;
rc.avg_st_encoding_bitrate += sum_bitrate2 / rc.window_size;
rc.variance_st_encoding_bitrate +=
(sum_bitrate2 / rc.window_size) *
(sum_bitrate2 / rc.window_size);
sum_bitrate2 = 0.0;
}
}
//decode
if( layer_id.temporal_layer_id == 0 ){
vpx_codec_control(&codec_dec, VP9E_SET_SVC_LAYER_ID, &layer_id);
vpx_codec_err_t res = vpx_codec_decode(&codec_dec, pkt->data.frame.buf, pkt->data.frame.sz, NULL, 0);
if( res )
die_codec(&codec_dec, "Failed to decode frame.");
vpx_codec_iter_t iter = NULL;
img_dec = vpx_codec_get_frame(&codec_dec, &iter);
if( img_dec == NULL )
die_codec(&codec_dec, "No frames were decoded.");
if( vpx_codec_get_frame(&codec_dec, &iter) != NULL )
die_codec(&codec_dec, "More than on frame decoded.");
printf( "decoded frame\n" );
}
break;
default: break;
}
}
++frame_cnt;
pts += frame_duration;
}
close_input_file(&input_ctx);
printout_rate_control_summary(&rc, &cfg, frame_cnt);
printf("\n");
printf("Frame cnt and encoding time/FPS stats for encoding: %d %f %f \n",
frame_cnt, 1000 * (float)cx_time / (double)(frame_cnt * 1000000),
1000000 * (double)frame_cnt / (double)cx_time);
if (vpx_codec_destroy(&codec)) die_codec(&codec, "Failed to destroy codec");
// Try to rewrite the output file headers with the actual frame count.
for (i = 0; i < cfg.ts_number_layers; ++i) vpx_video_writer_close(outfile[i]);
if (input_ctx.file_type != FILE_TYPE_Y4M) {
vpx_img_free(&raw);
}
#if ROI_MAP
free(roi.roi_map);
#endif
return EXIT_SUCCESS;
}
I got this errror during compile processing.
I already saw this error in this site before, I think this error can occur when the ; or something are in wrong place. but I can't find.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#define MAX 80
typedef struct assemble
{
int op;
int ni;
int xbpe;
int addr;
}Assemble;
void get_token(char *bp);
int hTod(char *dp);
int bTod(char *dp);
void codeBreak(char *cp);
void result(int t);
Assemble asm;
int type;
int main()
{
FILE *fp;
char buf[MAX];
if( (fp = fopen("inst.txt","r")) == NULL ){
fprintf(stderr, "file not found...\n"); exit(1);
}
while(fgets(buf,sizeof(buf),fp) != NULL){
get_token(buf);
}
fclose(fp);
return 0;
}
void get_token(char *bp)
{
char *cp;
int i = 1;
for(cp=strtok(bp, " \t\n"); cp != NULL; )
{
if( (*(cp+0) == '0') && (*(cp+1) == 'x') )
{
if( i == -1 )
asm.addr = hTod(cp);
if( i == 1)
asm.op = hTod(cp);
i *= -1;
}
else
{
codeBreak(cp);
}
cp = strtok(NULL, " \t\n");
}
result(type);
}
void codeBreak(char *cp)
{
if ( strlen(cp) == 2 ) // ni 판단
{
asm.ni = bTod(cp);
}
else if( strlen(cp) == 1 )
{
asm.xbpe = bTod(cp)*pow(2,3);
type = 1;
}
else if( strlen(cp) == 4 )
{
if( *(cp+3) == '1')
{
asm.xbpe = bTod(cp);
type = 2;
}
else
{
asm.xbpe = bTod(cp);
type = 3;
}
}
}
void result(int t)
{
switch(t)
{
case 1 : printf("0x%x%x\n", (asm.op+asm.ni), asm.addr); break;
case 2 : printf("0x%x%x%.5x\n", (asm.op+asm.ni), asm.xbpe, asm.addr); break;
case 3 : printf("0x%x%x%.3x\n", (asm.op+asm.ni), asm.xbpe, asm.addr); break;
default : break;
}
}
/* Hex to decimal */
int hTod(char *dp)
{
int i;
int dec = 0;
for( i=2 ; i < strlen(dp) ; i++)
{
switch (*(dp+i))
{
case 'a' : *(dp+i) = 58; break;
case 'b' : *(dp+i) = 59; break;
case 'c' : *(dp+i) = 60; break;
case 'd' : *(dp+i) = 61; break;
case 'e' : *(dp+i) = 62; break;
case 'f' : *(dp+i) = 63; break;
}
dec += (*(dp+i)-48) * pow( 16, (strlen(dp)-(i+1)));
}
return dec;
}
/* binary to decimal*/
int bTod(char *dp)
{
int i;
int dec = 0;
for( i = 0; i < strlen(dp) ; i++)
{
dec += (*(dp+i)-48) * pow( 2, (strlen(dp) - (i+1)));
}
return dec;
}
asm is a keyword. Instead of
Assemble asm;
use something different, such as:
Assemble asm1;
The problem reported by the compiler is different though. You seem to have used
ASSEMBLY asm;
in the code you compiled.
I wrote small daemon for rotating screen on Thinkpad X41 convertible laptop using built-in motion sensor (used by harddisk active protection system) or manually by button. Program works very well, but after some amount of time (5 to 15 minutes) will crash with segfault.
I know there are lot of scripts on the internet to do this written in bash or python, but none of them suit my needs and vision how should program work.
I know that for example mentioned bash is probably better for this, but I have zero experiences with it compared to C In which I have at least minimal basic experiences from few high school lessons, so I choose this.
here is the code:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#define TRUE 1
#define FALSE 0
#define NIL -1
#define XRANDR_GREP_COMMAND "xrandr -q --verbose|grep LVDS1|cut -b37-37"
#define DAEMON_LOCK_FILE "/dev/shm/thinkrotate.lock"
#define DAEMON_STATE_FILE "/dev/shm/thinkrotate.st"
#define SWIVEL_STATE_FILE "/sys/devices/platform/thinkpad_acpi/hotkey_tablet_mode"
#define GYRO_STATE_FILE "/sys/devices/platform/hdaps/position"
#define BUBBLE_TERMINATED "notify-send 'Ukončenie programu' 'ThinkRotate démon dostal príkaz na ukončenie'"
#define BUBBLE_SWIVEL_DOWN "notify-send 'Notebook v tablet móde' 'Veko bolo sklopené, aktivovaná automatická rotácia'"
#define BUBBLE_SWIVEL_UP "notify-send 'Notebook v štandartnom režime' 'Rotácia je deaktivovaná'"
#define BUBBLE_RETURN_POSITION "notify-send 'Automatická rotácia zapnutá' 'Pre vypnutie automatickej rotácie obrazu stlačte tlačítko rotácie.'"
#define BUBBLE_START_MANUAL_ROTATION "notify-send 'Automatická rotácia vypnutá' 'Rotácia bude zapnutá znovu až pri návrate do tejto polohy, dovtedy na otáčanie obrazu používajte tlačidlo.'"
#define SWIVEL_DOWN_COMMANDS ""
#define SWIVEL_UP_COMMANDS ""
#define WIDTH_COMMANDS ""
#define HEIGHT_COMMANDS ""
int get_lock(void) {
int fdlock;
struct flock fl;
fl.l_type = F_WRLCK;
fl.l_whence = SEEK_SET;
fl.l_start = 0;
fl.l_len = 1;
if((fdlock = open(DAEMON_LOCK_FILE, O_WRONLY|O_CREAT, 0666)) == -1) { return 0; }
if(fcntl(fdlock, F_SETLK, &fl) == -1) { return 0; }
return 1;
}
int next_rotation(int direction) {
int next;
int pos;
pos = current_pos();
if (direction == 1) {
switch (pos) {
case 0:
next = 1;
break;
case 1:
next = 2;
break;
case 2:
next = 3;
break;
case 3:
next = 0;
break;
}
} else if (direction == 2) {
switch (pos) {
case 0:
next = 3;
break;
case 1:
next = 0;
break;
case 2:
next = 1;
break;
case 3:
next = 2;
break;
}
}
return next;
}
int current_pos(void) {
FILE *frotpos;
char rotpos;
int pos;
frotpos = popen(XRANDR_GREP_COMMAND, "r");
fscanf(frotpos, "%c", &rotpos);
fclose(frotpos);
switch (rotpos) {
case 110:
pos = 0;
break;
case 108:
pos = 1;
break;
case 105:
pos = 2;
break;
case 114:
pos = 3;
break;
}
return pos;
}
void rotate(int poz) {
char buff[32];
if ((poz == 2)||(poz == 0)) {
system(WIDTH_COMMANDS);
} else {
system(HEIGHT_COMMANDS);
}
sprintf(buff, "xrandr -o %i", poz);
system(buff);
}
int main(int argc, char *argv[]) {
if(!get_lock()) {
if (argc >= 2) {
int cmd;
FILE *fparams;
fparams = fopen(DAEMON_STATE_FILE, "w");
if (!strncmp(argv[1], "r", 1)) { cmd = 1; }
else if (!strncmp(argv[1], "l", 1)) { cmd = 2; }
else if (!strncmp(argv[1], "k", 1)) { cmd = 0; }
fprintf(fparams, "%i", cmd);
fclose(fparams);
}
return 1;
}
int autorotate = TRUE;
int prevmode = NIL;
FILE *fstate;
int tabletmode;
FILE *fgyrovals;
char gyroval_x[5];
char gyroval_y[5];
int x;
int y;
FILE *fargs;
int argum = NIL;
int next_p;
int prev_p = current_pos();
int last_auto_p = NIL;
while (TRUE) {
fstate = fopen(SWIVEL_STATE_FILE, "r");
fscanf(fstate, "%d", &tabletmode);
if (fargs = fopen(DAEMON_STATE_FILE, "r")) {
if (fscanf(fargs, "%d", &argum) == NIL) { argum = NIL; }
}
fargs = fopen(DAEMON_STATE_FILE, "w");
fclose(fargs);
fclose(fstate);
if (argum == 0) {
system(BUBBLE_TERMINATED);
return 1;
}
if (prevmode != tabletmode) {
if (tabletmode) {
system(BUBBLE_SWIVEL_DOWN);
system(SWIVEL_DOWN_COMMANDS);
} else {
system(BUBBLE_SWIVEL_UP);
system(SWIVEL_UP_COMMANDS);
rotate(0);
}
}
if (tabletmode) {
if (argum == 1 || argum == 2) {
next_p = next_rotation(argum);
if (next_p == last_auto_p) {
rotate(next_p);
autorotate = TRUE;
last_auto_p = NIL;
system(BUBBLE_RETURN_POSITION);
} else if ((autorotate)&&(current_pos() == last_auto_p)) {
autorotate = FALSE;
system(BUBBLE_START_MANUAL_ROTATION);
} else {
if (autorotate) {
system(BUBBLE_START_MANUAL_ROTATION);
last_auto_p = current_pos();
} else {
rotate(next_p);
}
autorotate = FALSE;
}
}
if (autorotate) {
fgyrovals = fopen(GYRO_STATE_FILE, "r");
fscanf(fgyrovals, "(%4[^,], %4[^)]", &gyroval_x, &gyroval_y);
fclose(fgyrovals);
x = atoi(gyroval_x);
y = atoi(gyroval_y) * (-1);
if (y < 465) {
if (x < 210) {
next_p = 1;
} else if (x > 425) {
next_p = 3;
} else {
next_p = 2;
}
} else if (y > 525) {
if (x < 210) {
next_p = 1;
} else if (x > 425) {
next_p = 3;
} else {
next_p = 0;
}
} else {
if (x < 305) {
next_p = 1;
} else if (x > 345) {
next_p = 3;
}
}
if (next_p != prev_p) {
rotate(next_p);
prev_p = next_p;
}
}
} else {
if (argum == 1 || argum == 2) {
system(BUBBLE_SWIVEL_UP);
}
}
prevmode = tabletmode;
sleep(1);
}
return 0;
}
Thanks to comment of user "inspired". Now the program is running more than a hour without segfault.
if (fargs = fopen(DAEMON_STATE_FILE, "r")) {
if (fscanf(fargs, "%d", &argum) == NIL) { argum = NIL; }
fclose(fargs);
}
fargs = fopen(DAEMON_STATE_FILE, "w");
fclose(fargs);
As said, file should be closed before opened next time for writing.
I have a buffer overflow vulnerability in a simple webserver. It can be exploited with a http GET request. I'm having trouble figuring out how to fix it. My guess is that it has to do with: char hdrval[1024]; but I could be wrong. Can anyone else see whats wrong?
Code:
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <netdb.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <fcntl.h>
#include <time.h>
#include <pthread.h>
#define _XOPEN_SOURCE
typedef struct {
char *method;
char *uri;
char *version;
char *headers;
} httpreq_t;
/* NOTE: this function is based on a function provided in the GNU "timegm" man
page. timegm is a GNU extension to time.h that returns the given tm struct as
a UNIX timestamp in GMT/UTC, rather than local time. The man page suggests a
function similar to the one below as a portable equivalent.
*/
time_t my_timegm(struct tm *tm) {
time_t ret;
char *tz;
tz = getenv("TZ");
putenv("TZ=GMT");
tzset();
ret = mktime(tm);
if (tz) {
char envstr[strlen(tz) + 4];
envstr[0] = '\0';
strcat(envstr, "TZ=");
strcat(envstr, tz);
putenv(envstr);
} else {
putenv("TZ=");
}
tzset();
return ret;
}
char *get_header(const httpreq_t *req, const char* headername) {
char *hdrptr;
char *hdrend;
char *retval = NULL;
char searchstr[strlen(headername) + 5];
strcpy(searchstr, "\r\n");
strcat(searchstr, headername);
strcat(searchstr, ": ");
if (hdrptr = strstr(req->headers, searchstr)) {
hdrptr += strlen(searchstr);
if (hdrend = strstr(hdrptr, "\r\n")) {
char hdrval[1024]; // temporary return value
memcpy((char *)hdrval, hdrptr, (hdrend - hdrptr));
hdrval[hdrend - hdrptr] = '\0'; // tack null onto end of header value
int hdrvallen = strlen(hdrval);
retval = (char *)malloc((hdrvallen + 1) * sizeof(char)); // malloc a space for retval
strcpy(retval, (char *)hdrval);
} else {
retval = (char *)malloc((strlen(hdrptr) + 1) * sizeof(char)); //
strcpy(retval, hdrptr);
}
}
return retval;
}
/* As long as str begins with a proper HTTP-Version followed by delim, returns a
pointer to the start of the version number (e.g., 1.0). Returns NULL otherwise.
*/
char *http_version_str(char *str, char *delim) {
char *vstart = strstr(str, "HTTP/");
char *vnumstart = str + 5;
char *vdot = strchr(str, '.');
char *vend = strstr(str, delim);
char *digits = "0123456789";
int majvlen = 0;
int minvlen = 0;
if (!vstart || !vdot // something's missing
|| vstart != str) // str doesn't start with "HTTP/"
return NULL;
majvlen = strspn(vnumstart, digits);
minvlen = strspn(vdot + 1, digits);
if (majvlen < 1 || (vnumstart + majvlen) != vdot // bad major version
|| minvlen < 1 || (vdot + minvlen + 1) != vend) // bad minor version
return NULL;
return vnumstart;
}
/* Fills req with the request data from datastr. Returns 0 on success.
*/
int parsereq(httpreq_t *req, char *datastr) {
char *position;
char *last_position = datastr;
char *temp_position;
int matchlen;
req->method = "";
req->uri = "";
req->version = "";
req->headers = "";
if (!(position = strchr(last_position, ' '))) {
return 1;
}
matchlen = (int)(position - last_position);
req->method = (char *)malloc((matchlen + 1) * sizeof(char));
memcpy(req->method, last_position, matchlen);
req->method[matchlen] = '\0';
last_position = position + 1;
if (!(position = strchr(last_position, ' '))
&& !(position = strstr(last_position, "\r\n"))) {
return 1;
}
// strip any query string out of the URI
if ((temp_position = strchr(last_position, '?')) && temp_position < position)
matchlen = (int)(temp_position - last_position);
else
matchlen = (int)(position - last_position);
req->uri = (char *)malloc((matchlen + 1) * sizeof(char));
memcpy(req->uri, last_position, matchlen);
req->uri[matchlen] = '\0';
if (position[0] == '\r') {
req->version = "0.9";
req->headers = "";
return 0; // simple req -- uri only
}
// If we get here, it's a full request, get the HTTP version and headers
last_position = position + 1;
if (!(position = strstr(last_position, "\r\n"))
|| !(last_position = http_version_str(last_position, "\r\n"))) {
return 1;
}
matchlen = (int)(position - last_position);
req->version = (char *)malloc((matchlen + 1) * sizeof(char));
memcpy(req->version, last_position, matchlen);
req->version[matchlen] = '\0';
last_position = position;
req->headers = (char *)malloc(strlen(last_position) * sizeof(char));
strcpy(req->headers, last_position);
return 0;
}
char *contype(char *ext) {
if (strcmp(ext, "html") == 0) return "text/html";
else if (strcmp(ext, "htm") == 0) return "text/html";
else if (strcmp(ext, "jpeg") == 0) return "image/jpeg";
else if (strcmp(ext, "jpg") == 0) return "image/jpeg";
else if (strcmp(ext, "gif") == 0) return "image/gif";
else if (strcmp(ext, "txt") == 0) return "text/plain";
else return "application/octet-stream";
}
char *status(int statcode) {
if (statcode == 200) return "200 OK";
else if (statcode == 304) return "304 Not Modified";
else if (statcode == 400) return "400 Bad Request";
else if (statcode == 403) return "403 Forbidden";
else if (statcode == 404) return "404 Not Found";
else if (statcode == 500) return "500 Internal Server Error";
else if (statcode == 501) return "501 Not Implemented";
else return "";
}
int send_response(int sockfd, httpreq_t *req, int statcode) {
int urifd;
const int BUFSIZE = 1024;
char sendmessage[BUFSIZE];
char *path = req->uri;
if (req->uri == NULL || req->method == NULL ||
req->headers == NULL || req->version == NULL) {
return 0;
}
if ((path[0] == '/') || ((strstr(path, "http://") == path)
&& (path = strchr(path + 7, '/')))) {
path += 1; // remove leading slash
if (path[0] == '\0') { // substituting in index.html for a blank URL!
path = "index.html";
} else if (path[strlen(path) - 1] == '/') {
//concatenating index.html for a /-terminated URL!
strcat(path, "index.html");
}
} else {
statcode = 400;
}
if (statcode == 200 && (urifd = open(path, O_RDONLY, 0)) < 0) {
if (errno == ENOENT || errno == ENOTDIR) { // file or directory doesn't exist
statcode = 404;
} else if (errno == EACCES) { // access denied
statcode = 403;
} else {
// some other file access problem
statcode = 500;
}
}
if (strstr(path, "..") != NULL) {
statcode = 500;
}
sendmessage[0] = '\0';
if (strcmp(req->version, "0.9") != 0) { // full request
char *ext; // file extension
time_t curtime;
char *imstime;
struct tm tm;
struct stat stbuf;
if (statcode == 200) {
if (ext = strrchr(path, '.')) ext++; // skip the '.'
else ext = "";
} else {
// errors are always html messages
ext = "html";
}
// Conditional GET
if ((strcmp(req->method, "GET") == 0)
&& (statcode == 200)
&& (imstime = get_header(req, "If-Modified-Since"))) {
// Get statistics about the requested URI from the local filesystem
if (stat(path, &stbuf) == -1) {
statcode = 500;
}
if (!strptime(imstime, "%a, %d %b %Y %H:%M:%S GMT", &tm)
&& !strptime(imstime, "%a, %d-%b-%y %H:%M:%S GMT", &tm)
&& !strptime(imstime, "%a %b %d %H:%M:%S %Y", &tm)) {
// badly formatted date
statcode = 400;
}
if (stbuf.st_mtime <= my_timegm(&tm)) {
// Not Modified
statcode = 304;
}
}
time(&curtime); // time for Date: header
strcat(sendmessage, "HTTP/1.0 ");
strcat(sendmessage, status(statcode));
strcat(sendmessage, "\r\nDate: ");
strncat(sendmessage, asctime(gmtime(&curtime)), 24);
strcat(sendmessage, "\r\nServer: Frobozz Magic Software Company Webserver v.002");
strcat(sendmessage, "\r\nConnection: close");
strcat(sendmessage, "\r\nContent-Type: ");
strcat(sendmessage, contype(ext));
strcat(sendmessage, "\r\n\r\n");
}
if (statcode != 200) {
strcat(sendmessage, "<html><head><title>");
strcat(sendmessage, status(statcode));
strcat(sendmessage, "</title></head><body><h2>HTTP/1.0</h2><h1>");
strcat(sendmessage, status(statcode));
strcat(sendmessage, "</h1><h2>URI: ");
strcat(sendmessage, path);
strcat(sendmessage, "</h2></body></html>");
}
if (sendmessage[0] != '\0') {
// send headers as long as there are headers to send
if (send(sockfd, sendmessage, strlen(sendmessage), 0) < 0) {
perror("send");
pthread_exit(NULL);
}
}
if (statcode == 200 && (strcmp(req->method, "HEAD") != 0)) {
// send the requested file as long as there's no error and the
// request wasn't just for the headers
int readbytes;
while (readbytes = read(urifd, sendmessage, BUFSIZE)) {
if (readbytes < 0) {
perror("read");
pthread_exit(NULL);
}
if (send(sockfd, sendmessage, readbytes, 0) < 0) {
perror("send");
pthread_exit(NULL);
}
}
}
}
void *data_thread(void *sockfd_ptr) {
int sockfd = *(int *) sockfd_ptr;
const int BUFSIZE = 5;
char recvmessage[BUFSIZE];
char *headerstr = NULL;
char *newheaderstr = NULL;
int recvbytes = 0;
int curheadlen = 0;
int totalheadlen = 0;
httpreq_t req;
int statcode = 200;
int done = 0;
int seen_header = 0;
char *header_end;
int content_length = 0;
char *qstr;
free(sockfd_ptr); // we have the int value out of this now
recvmessage[BUFSIZE - 1] = '\0'; // mark end of "string"
/* Read incoming client message from the socket */
while(!done && (recvbytes = recv(sockfd, recvmessage, BUFSIZE - 1, 0))) {
if (recvbytes < 0) {
perror("recv");
pthread_exit(NULL);
}
recvmessage[recvbytes] = '\0';
if (seen_header) {
// getting the entity body
content_length -= recvbytes;
if (content_length <= 0) done = 1;
} else {
newheaderstr = (char *) malloc((totalheadlen + recvbytes + 1) * sizeof(char));
newheaderstr[totalheadlen + recvbytes] = '\0';
memcpy(newheaderstr, headerstr, totalheadlen);
memcpy(newheaderstr + totalheadlen, recvmessage, recvbytes);
if (headerstr) free(headerstr);
headerstr = newheaderstr;
totalheadlen += recvbytes;
header_end = strstr(headerstr, "\r\n\r\n");
if (header_end) {
seen_header = 1;
header_end[2] = '\0';
if (parsereq(&req, headerstr) != 0) {
statcode = 400;
}
if (strcmp(req.method, "POST") == 0) {
// grab the body length
char *clenstr = get_header(&req, "Content-Length");
if (clenstr) {
content_length = atoi(clenstr) - ((headerstr + totalheadlen) - header_end - 4);
if (content_length <= 0) done = 1;
free(clenstr);
} else {
statcode = 400; // bad request -- no content length
done = 1;
}
} else {
// This isn't a POST, so there's no entity body
done = 1;
if (strcmp(req.method, "GET") != 0
&& strcmp(req.method, "HEAD") != 0) {
statcode = 501; // unknown request method
}
}
}
}
} // end of recv while loop
// used to deref a NULL pointer here... :(
if (headerstr != NULL) {
printf("%s\n", headerstr);
free(headerstr);
}
send_response(sockfd, &req, statcode);
close(sockfd);
return NULL;
}
int main(int argc, char *argv[]) {
int acc, sockfd, clen, port;
struct hostent *he;
struct sockaddr_in caddr, saddr;
if(argc <= 1) {
fprintf(stderr, "No port specified. Exiting!\n");
exit(1);
}
port = atoi(argv[1]);
/* Obtain name and address for the local host */
if((he=gethostbyname("localhost"))==NULL) {
herror("gethostbyname");
exit(1);
}
/* Open a TCP (Internet Stream) socket */
if((sockfd=socket(AF_INET,SOCK_STREAM,0)) == -1) {
perror("socket");
exit(1);
}
/* Create socket address structure for the local host */
memset((char *) &saddr, '\0', sizeof(saddr));
saddr.sin_family=AF_INET;
saddr.sin_port=htons(port);
saddr.sin_addr.s_addr=htonl(INADDR_ANY);
/* Bind our local address so that the client can send to us */
if(bind(sockfd,(struct sockaddr *) &saddr,sizeof(saddr)) == -1) {
perror("bind");
exit(1);
}
if(listen(sockfd,5) < 0) {
perror("listen");
exit(1);
}
/* Infinite loop for receiving and processing client requests */
for(;;) {
clen=sizeof(caddr);
/* Wait for a connection for a client process */
acc=accept(sockfd,(struct sockaddr *) &caddr,(socklen_t*)&clen);
if(acc < 0) {
perror("accept");
exit(1);
} else {
pthread_t *thread = (pthread_t *) malloc(sizeof(pthread_t));
int *sockfd_ptr = (int *) malloc(sizeof(int));
*sockfd_ptr = acc;
pthread_create(thread, NULL, data_thread, sockfd_ptr);
}
}
return 0;
}
I guess you could have a bound check before copying to the buffer?
For example, add
if(hdrend - hdrptr >= 1024)
exit(1)
before
memcpy((char *)hdrval, hdrptr, (hdrend - hdrptr));
The segfault happens at the point below.
Program received signal SIGSEGV, Segmentation fault.
[Switching to Thread 0xb7ff4b70 (LWP 3902)]
Program received signal SIGSEGV, Segmentation fault.
[Switching to Thread 0xb7ff4b70 (LWP 3902)]
0x08049507 in send_response (sockfd=6, req=0xb7ff4340, statcode=200)
at server/webserver.c:219
warning: Source file is more recent than executable.
219 if (req->uri == NULL || req->method == NULL ||
The memory address is
(gdb) p $_siginfo._sifields._sigfault.si_addr
$3 = (void *) 0x69cb120
The code that needs to be rewritten is
214 int urifd;
215 const int BUFSIZE = 1024;
216 char sendmessage[BUFSIZE];
217 char *path = req->uri;
218
219 if (req->uri == NULL || req->method == NULL ||
220 req->headers == NULL || req->version == NULL) {
221 return 0;