100% cpu usage with a libpcap simple example - c

while running the code below, one of the CPU cores reaches 100% usage. With or without traffic. What is wrong?
Example code:
#include <stdio.h>
#include <stdlib.h>
#include <pcap.h>
#include <errno.h>
void my_callback(u_char *args, const struct pcap_pkthdr* pkthdr, const u_char*
packet)
{
//nothing, nothing at all...
//printf("+");
}
int main(int argc,char **argv)
{
int i;
char *dev;
char errbuf[PCAP_ERRBUF_SIZE];
pcap_t* descr;
const u_char *packet;
struct bpf_program fp; /* hold compiled program */
bpf_u_int32 maskp; /* subnet mask */
bpf_u_int32 netp; /* ip */
if(argc != 2){
fprintf(stdout, "Usage: %s \"expression\"\n"
,argv[0]);
return 0;
}
/* Now get a device */
dev = pcap_lookupdev(errbuf);
if(dev == NULL) {
fprintf(stderr, "%s\n", errbuf);
exit(1);
}
/* Get the network address and mask */
pcap_lookupnet(dev, &netp, &maskp, errbuf);
/* open device for reading in promiscuous mode */
descr = pcap_open_live(dev, BUFSIZ, 1,-1, errbuf);
if(descr == NULL) {
printf("pcap_open_live(): %s\n", errbuf);
exit(1);
}
/* Now we'll compile the filter expression*/
if(pcap_compile(descr, &fp, argv[1], 0, netp) == -1) {
fprintf(stderr, "Error calling pcap_compile\n");
exit(1);
}
/* set the filter */
if(pcap_setfilter(descr, &fp) == -1) {
fprintf(stderr, "Error setting filter\n");
exit(1);
}
/* loop for callback function */
pcap_loop(descr, -1, my_callback, NULL);
return 0;
}
compile with: gcc example.c -o example -lpcap
run with: ./example "tcp" or the filter you like.
As you can see it is the typical example, the main and the callback function for the loop: pcap_loop(descr, -1, my_callback, NULL);
The callback is empty (useless) but it is just to show that the problem is not in the callback.

You specified timeout -1 here:
descr = pcap_open_live(dev, BUFSIZ, 1,-1, errbuf);
It turns pcap_loop into a busy loop, as poll continuously times out instantly.
Use something like 1000 (milliseconds) if you have no reason for other value.

Related

Why pcap_set_rfmon fails each time?

I'm working on a low level sniffer based on libpcap. Everything works perfectly but the assert with pcap_set_rfmon() fails each time. I don't think that I made any mistake to get this result. I post a little snippet of the main function. If you have some ideas about a solution, it would be helpful. I tried with various NICs and dongles but on none of them, the monitor mode can be set.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pcap.h>
#define JUMBO_FRAMES_MTU 9000
#define BIGGER_THAN_ALL_MTUS (64*1024)
#define ERR(msg) do { perror(msg); exit(EXIT_FAILURE); } while (0)
int main(int argc, char **argv)
{
char errbuf[PCAP_ERRBUF_SIZE];
pcap_t *handle;
if (argc < 2){
ERR("usage : ./prog itf-name\n");
}
/* exiting if strlen of itf > 14 */
if (strlen(argv[1]) > IFNAMSIZ){
ERR("Interface name too long");
}
strncpy(opt_args->device, argv[1], strlen(argv[1]) + 1);
handle = pcap_create(opt_args->device, errbuf);
if (handle == NULL){
(void)fprintf(stderr, "FATAL ERROR : couldn't create sock handle : %s\n", errbuf);
goto fatal_error;
}
/* setting snaplen to 1500 */
assert(pcap_set_snaplen(handle, ETHERNET_MTU) == 0);
assert(pcap_setnonblock(handle, -1, errbuf) != -1);
/* if we can't put the device in monitor mode, so we display a warning
but keep doing the capture */
/* I have a warning here */
if (pcap_can_set_rfmon(handle) != 1){
(void)fprintf(stderr, "WARNING : device can't be set up in monitor mode : %s\n",
pcap_geterr(handle));
} else{
assert(pcap_set_rfmon(handle, 1) == 0);
}
/* we need now to launch the session capture */
if (pcap_activate(handle) < 0){
(void)fprintf(stderr, "FATAL ERROR : couldn't activate PCAP sock : %s\n",
pcap_geterr(handle));
goto fatal_error;
}
/* pcap loop ... */
pcap_close(handle);
return 0;
fatal_error;
pcap_close(handle);
return 1;
}

ebpf program function is not triggering prints nothing in simple program hook for kprobe function that exists in proc/kallsyms file

So I have this function in my driver for network NIC and this function appears in proc/kallsyms[https://stackoverflow.com/a/67766463/4808760] file with base address this is the function
static int rtl8169_poll(struct napi_struct *napi, int budget)
{
struct rtl8169_private *tp = container_of(napi, struct rtl8169_private, napi);
struct net_device *dev = tp->dev;
int work_done;
rtl_tx(dev, tp, budget);
work_done = rtl_rx(dev, tp, budget);
if (work_done < budget && napi_complete_done(napi, work_done))
rtl_irq_enable(tp);
return work_done;
}
appears as
ffffffffc02d2210 t rtl8169_poll [r8169]
and this is my ebpf program
SEC("kprobe/rtl8169_poll")
int bpf_prog2(struct pt_regs *ctx)
{
int sc_nr = (int)PT_REGS_PARM1(ctx);
char *fmt="HELLO from FWDALI %d %d";
bpf_trace_printk(fmt,1,sc_nr);
bpf_trace_printk(fmt ,2,sc_nr);
/* dispatch into next BPF program depending on syscall number */
//bpf_tail_call(ctx, &progs, sc_nr);
/* fall through -> unknown syscall */
//if (sc_nr >= __NR_getuid && sc_nr <= __NR_getsid) {
// char fmt[] = "-----FWD-------------------------syscall=%d (one of get/set uid/pid/gid)\n";
// bpf_trace_printk(fmt, sizeof(fmt), sc_nr);
//}
return 0;
}
And this is my simple userspace code
// SPDX-License-Identifier: GPL-2.0
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <linux/filter.h>
#include <linux/seccomp.h>
#include <sys/prctl.h>
#include <bpf/bpf.h>
#include <bpf/libbpf.h>
#include <sys/resource.h>
#include <fcntl.h>
#ifdef __mips__
#define MAX_ENTRIES 6000 /* MIPS n64 syscalls start at 5000 */
#else
#define MAX_ENTRIES 1024
#endif
/* install fake seccomp program to enable seccomp code path inside the kernel,
* so that our kprobe attached to seccomp_phase1() can be triggered
*/
void read_trace_pipe(void)
{
int trace_fd;
//printf("-%s-\n",DEBUGFS);
trace_fd = open( "/sys/kernel/debug/tracing/trace_pipe", O_RDONLY, 0);
if (trace_fd < 0)
return;
while (1) {
static char buf[4096];
ssize_t sz;
sz = read(trace_fd, buf, sizeof(buf) - 1);
if (sz > 0) {
buf[sz] = 0;
puts(buf);
}
}
}
static void install_accept_all_seccomp(void)
{
struct sock_filter filter[] = {
BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_ALLOW),
};
struct sock_fprog prog = {
.len = (unsigned short)(sizeof(filter)/sizeof(filter[0])),
.filter = filter,
};
if (prctl(PR_SET_SECCOMP, 2, &prog))
perror("prctl");
}
int main(int ac, char **argv)
{
struct bpf_link *link = NULL;
struct bpf_program *prog;
struct bpf_object *obj;
int key, fd, progs_fd;
const char *section;
char filename[256];
FILE *f;
snprintf(filename, sizeof(filename), "%s_kern.o", argv[1]);
obj = bpf_object__open_file(filename, NULL);
if (libbpf_get_error(obj)) {
fprintf(stderr, "ERROR: opening BPF object file failed\n");
return 0;
}
prog = bpf_object__find_program_by_name(obj, "bpf_prog2");
if (!prog) {
printf("finding a prog in obj file failed\n");
goto cleanup;
}
/* load BPF program */
if (bpf_object__load(obj)) {
fprintf(stderr, "ERROR: loading BPF object file failed\n");
goto cleanup;
}
link = bpf_program__attach(prog);
if (libbpf_get_error(link)) {
fprintf(stderr, "ERROR: bpf_program__attach failed\n");
link = NULL;
goto cleanup;
}
progs_fd = bpf_object__find_map_fd_by_name(obj, "progs");
if (progs_fd < 0) {
fprintf(stderr, "ERROR: finding a map in obj file failed\n");
goto cleanup;
}
bpf_object__for_each_program(prog, obj) {
section = bpf_program__section_name(prog);
/* register only syscalls to PROG_ARRAY */
if (sscanf(section, "kprobe/%d", &key) != 1)
continue;
fd = bpf_program__fd(prog);
bpf_map_update_elem(progs_fd, &key, &fd, BPF_ANY);
}
install_accept_all_seccomp();
f = popen("dd if=/dev/zero of=/dev/null count=5", "r");
(void) f;
read_trace_pipe();
cleanup:
bpf_link__destroy(link);
bpf_object__close(obj);
return 0;
}
SO i like if some take a look at above and explain what exactly I need to add to my ebpf program for kprobe and also what I need to do in my userspace loader program..
I am still having tough time with getting to loads of stuff that tells its simple to implement to use this magical line SEC("kprobe/rtl8169_poll") or something with just loading the program from userspace and its done, But I havent started thinking much of ebpf since ebpf is kind of failed in this simple function hook
this link gave me the idea that I can hook to this function https://stackoverflow.com/a/67766463/4808760

Unix system programming: get a network identifier to be passed to getaddrinfo

I am following on a book the code in C to build a server using system calls.
The main function is the following:
int main(int argc, char* argv[])
{
printf("entered main\n");
struct addrinfo *ailist, *aip, hint;
int sockfd, err, n;
char *host;
if (argc != 1)
{
printf("usage: ruptimed\n");
exit(1);
}
if ((n=sysconf(_SC_HOST_NAME_MAX))<0)
{
n = HOST_NAME_MAX;
}
if((host = malloc(n)) == NULL)
{
printf("malloc error\n");
exit(1);
}
if (gethostname(host, n)<0)
{
printf("gethostname error\n");
exit(1);
}
printf("host: %s\n", host);
printf("Daemonizing\n");
int res = daemonize("ruptimed");
printf("%d\n", res);
printf("Daemonized\n");
memset(&hint, 0, sizeof(hint)); //set to 0 all bytes
printf("hint initialized\n");
hint.ai_flags = AI_CANONNAME;
hint.ai_socktype = SOCK_STREAM;
hint.ai_canonname = NULL;
hint.ai_addr = NULL;
hint.ai_next = NULL;
printf("getting addresses\n");
if((err = getaddrinfo(host, "ruptime", &hint, &ailist))!=0)
{
printf("error %s\n", gai_strerror(err));
syslog(LOG_ERR, "ruptimed: getaddrinfo error %s", gai_strerror(err));
exit(1);
}
printf("Got addresses\n");
for (aip = ailist; aip!=NULL; aip = aip->ai_next)
{
if ((sockfd = initserver(SOCK_STREAM, aip->ai_addr, aip->ai_addrlen, QLEN))>=0)
{
printf("starting to serve\n");
serve(sockfd);
exit(0);
}
}
exit(1);
}
My problem is when getting the host name with gethostname and then using it with getaddrinfo.
Running the code on OSX I get a name such as pippo's-MacBook-pro.local memorized in the host char pointer variable. Passing this to getaddrinfo results in the error: nodename nor servname provided, or not known.
I was expecting the gethostname to return a local IP or a local network identifier (even localhost would be good for learning). I doubt such name can be used to identify a (local) server without proper settings on the machine (plus I cannot remember the book saying anything about setting the host name).
How can I get a network identifier (such as the local IP) to be passed to getaddrinfo?
If I would like to use gethostname what changes or settings should be performed?
CODE
server.c
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h> //_SC_HOST_NAME_MAX
#include<string.h>
#include<netdb.h> //Here are defined AF_INET and the others of the family
#include<syslog.h> //LOG_ERR
#include<errno.h> //errno
#include <sys/types.h>
#include"utilities.h"
#include "error.h"
#define BUFLEN 128
#define QLEN 10
#ifndef HOST_NAME_MAX
#define HOST_NAME_MAX 156
#endif
int initserver(int type, const struct sockaddr *addr, socklen_t alen, int qlen);
void serve(int sockfd);
int main(int argc, char* argv[])
{
printf("entered main\n");
struct addrinfo *ailist, *aip, hint;
int sockfd, err, n;
char *host;
if (argc != 1)
{
printf("usage: ruptimed\n");
exit(1);
}
if ((n=sysconf(_SC_HOST_NAME_MAX))<0)
{
n = HOST_NAME_MAX;
}
if((host = malloc(n)) == NULL)
{
printf("malloc error\n");
exit(1);
}
if (gethostname(host, n)<0)
{
printf("gethostname error\n");
exit(1);
}
printf("host: %s\n", host);
printf("Daemonizing\n");
int res = daemonize("ruptimed");
printf("%d\n", res);
printf("Daemonized\n");
memset(&hint, 0, sizeof(hint)); //set to 0 all bytes
printf("hint initialized\n");
hint.ai_flags = AI_CANONNAME;
hint.ai_socktype = SOCK_STREAM;
hint.ai_canonname = NULL;
hint.ai_addr = NULL;
hint.ai_next = NULL;
printf("getting addresses\n");
if((err = getaddrinfo(host, "ruptime", &hint, &ailist))!=0)
{
printf("error %s\n", gai_strerror(err));
syslog(LOG_ERR, "ruptimed: getaddrinfo error %s", gai_strerror(err));
exit(1);
}
printf("Got addresses\n");
for (aip = ailist; aip!=NULL; aip = aip->ai_next)
{
if ((sockfd = initserver(SOCK_STREAM, aip->ai_addr, aip->ai_addrlen, QLEN))>=0)
{
printf("starting to serve\n");
serve(sockfd);
exit(0);
}
}
exit(1);
}
void serve(int sockfd)
{
int clfd;
FILE *fp;
char buf[BUFLEN];
set_cloexec(sockfd);
for(;;)
{
/*After listen, the socket can receive connect requests. accept
retrieves a connect request and converts it into a connection.
The file returned by accept is a socket descriptor connected to the client that
called connect, haing the same coket type and family type. The original
soket remains available to receive otherconneion requests. If we don't care
about client's identity we can set the second (struct sockaddr *addr)
and third parameter (socklen_t *len) to NULL*/
if((clfd = accept(sockfd, NULL, NULL))<0)
{
/*This generates a log mesage.
syslog(int priority, const char *fformat,...)
priority is a combination of facility and level. Levels are ordered from highest to lowest:
LOG_EMERG: emergency system unusable
LOG_ALERT: condiotin that must be fied immediately
LOG_CRIT: critical condition
LOG_ERR: error condition
LOG_WARNING
LOG_NOTICE
LOG_INFO
LOG_DEBUG
format and other arguments are passed to vsprintf function forf formatting.*/
syslog(LOG_ERR, "ruptimed: accept error: %s", strerror(errno));
exit(1);
}
/* set the FD_CLOEXEC file descriptor flag */
/*it causes the file descriptor to be automatically and atomically closed
when any of the exec family function is called*/
set_cloexec(clfd);
/**pg. 542 Since a common operation is to create a pipe to another process
to either read its output or write its input Stdio has provided popen and
pclose: popen creates pipe, close the unused ends of the pipe,
forks a child and call exec to execute cmdstr and
returns a file pointer (connected to std output if "r", to stdin if "w").
pclose closes the stream, waits for the command to terminate*/
if ((fp = popen("/usr/bin/uptime", "r")) == NULL)
{
/*sprintf copy the string passed as second parameter inside buf*/
sprintf(buf, "error: %s\n", strerror(errno));
/*pag 610. send is similar to write. send(int sockfd, const void *buf, size_t nbytes, it flags)*/
send(clfd, buf, strlen(buf),0);
}
else
{
/*get data from the pipe that reads created to exec /usr/bin/uptime */
while(fgets(buf, BUFLEN, fp)!=NULL)
{
/* clfd is returned by accept and it is a socket descriptor
connected to the client that called connect*/
send(clfd, buf, strlen(buf), 0);
}
/*see popen pag. 542*/
pclose(fp);
}
close(clfd);
}
}
int initserver(int type, const struct sockaddr *addr, socklen_t alen, int qlen)
{
int fd, err;
int reuse = 1;
if ((fd = socket(addr->sa_family, type, 0))<0)
{
return (-1);
}
if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(int))<0)
{
goto errout;
}
if(bind(fd, addr, alen)<0)
{
goto errout;
}
if (type == SOCK_STREAM || type == SOCK_SEQPACKET)
{
if(listen(fd, qlen)<0)
{
goto errout;
}
}
return fd;
errout:
err = errno;
close (fd);
errno = err;
return(-1);
}
utilities.c: containing the demonize and setcloexec functions. In daemonize function I did not close file descriptors for debugging.
#include "utilities.h"
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <syslog.h>
#include <sys/time.h>//getrlimit
#include <sys/resource.h>//getrlimit
#include <signal.h> //sigempyset , asigcation (umask?)
#include <sys/resource.h>
#include <fcntl.h> //O_RDWR
#include <stdarg.h>
#include "error.h"
int daemonize(const char *cmd)
{
int fd0, fd1, fd2;
unsigned int i;
pid_t pid;
struct rlimit rl;
struct sigaction sa;
/* *Clear file creation mask.*/
umask(0);
/* *Get maximum number of file descriptors. */
if (getrlimit(RLIMIT_NOFILE, &rl) < 0)
{
err_quit("%s: can’t get file limit", cmd);
}
/* *Become a session leader to lose controlling TTY. */
if ((pid = fork()) < 0)
{
err_quit("%s: can’t fork", cmd);
}
else if (pid != 0) /* parent */
{
exit(0); //the parent will exit
}
setsid();
/* *Ensure future opens won’t allocate controlling TTYs. */
sa.sa_handler = SIG_IGN;
sigemptyset(&sa.sa_mask);
sa.sa_flags = 0;
if (sigaction(SIGHUP, &sa, NULL) < 0)
{
err_quit("%s: can’t ignore SIGHUP", cmd);
}
if ((pid = fork()) < 0)
{
err_quit("%s: can’t fork", cmd);
}
else if (pid != 0) /* parent */
{
exit(0);
}
/*
*Change the current working directory to the root so
* we won’t prevent file systems from being unmounted.
*/
if (chdir("/") < 0)
{
err_quit("%s: can’t change directory to /", cmd);
}
/* Close all open file descriptors. */
if (rl.rlim_max == RLIM_INFINITY)
{
rl.rlim_max = 1024;
}
printf("closing file descriptors\n");
/*for (i = 0; i < rl.rlim_max; i++)
{
close(i);
}*/
/* *Attach file descriptors 0, 1, and 2 to /dev/null.*/
//printf not working
/*printf("closed all file descriptors for daemonizing\n");*/
/*fd0 = open("/dev/null", O_RDWR);
fd1 = dup(0);
fd2 = dup(0);*/
/* *Initialize the log file. Daemons do not have a controlling terminal so
they can't write to stderror. We don't want them to write to the console device
because on many workstations the control device runs a windowing system. They can't
write on separate files either. A central daemon error-logging facility is required.
This is the BSD. 3 ways to generate log messages:
1) kernel routines call the log function. These messages can be read from /dev/klog
2) Most user processes (daemons) call syslog to generate log messages. This causes
messages to be sent to the UNIX domain datagram socket /dev/log
3) A user process on this host or on other host connected to this with TCP/ID
can send log messages to UDP port 514. Explicit network programmin is required
(it is not managed by syslog.
The syslogd daemon reads al three of log messages.
openlog is optional since if not called, syslog calls it. Also closelog is optional
openlog(const char *ident, int option, int facility)
It lets us specify ident that is added to each logmessage. option is a bitmask:
LOG_CONS tells that if the log message can't be sent to syslogd via UNIX
domain datagram, the message is written to the console instead.
facility lets the configuration file specify that messages from different
facilities are to be handled differently. It can be specified also in the 'priority'
argument of syslog. LOG_DAEMON is for system deamons
*/
/*
openlog(cmd, LOG_CONS, LOG_DAEMON);
if (fd0 != 0 || fd1 != 1 || fd2 != 2)
{*/
/*This generates a log mesage.
syslog(int priority, const char *fformat,...)
priority is a combination of facility and level. Levels are ordered from highest to lowest:
LOG_EMERG: emergency system unusable
LOG_ALERT: condiotin that must be fied immediately
LOG_CRIT: critical condition
LOG_ERR: error condition
LOG_WARNING
LOG_NOTICE
LOG_INFO
LOG_DEBUG
format and other arguments are passed to vsprintf function forf formatting.*/
/*syslog(LOG_ERR, "unexpected file descriptors %d %d %d", fd0, fd1, fd2);
exit(1);
}*/
return 0;
}
/*The function set the FD_CLOEXEC flag of the file descriptor already open that
is passed to as parameter. FD_CLOEXEC causes the file descriptor to be
automatically and atomically closed when any of the exec family function is
called*/
int set_cloexec(int fd)
{
int val;
/* retrieve the flags of the file descriptor */
if((val = fcntl(fd, F_GETFD, 0))<0)
{
return -1;
}
/* set the FD_CLOEXEC file descriptor flag */
/*it causes the file descriptor to be automatically and atomically closed
when any of the exec family function is called*/
val |= FD_CLOEXEC;
return (fcntl(fd, F_SETFD, val));
}
error functions I used
/* Fatal error unrelated to a system call.
* Print a message and terminate*/
void err_quit (const char *fmt, ...)
{
va_list ap;
va_start (ap, fmt);
err_doit (0, 0, fmt, ap);
va_end (ap);
exit(1);
}
/*Print a message and return to caller.
*Caller specifies "errnoflag"*/
static void err_doit(int errnoflag, int error, const char *fmt, va_list ap)
{
char buf [MAXLINE];
vsnprintf (buf, MAXLINE-1, fmt, ap);
if (errnoflag)
{
snprintf (buf+strlen(buf), MAXLINE-strlen(buf)-1, ": %s",
strerror (error));
}
strcat(buf, "\n");
fflush(stdout); /*in case stdout and stderr are the same*/
fputs (buf, stderr);
fflush(NULL); /* flushes all stdio output streams*/
}
There is a relatively simple typo in the getaddrinfo call
if((err = getaddrinfo("host", "ruptime", &hint, &ailist))!=0)
/* ^^^^^^ */
/* Should be the variable host */
{
printf("error %s\n", gai_strerror(err));
syslog(LOG_ERR, "ruptimed: getaddrinfo error %s", gai_strerror(err));
exit(1);
}
The code is looking for the address of "host". I would also replace "ruptime" with NULL since ruptime isn't an entry in /etc/services. See getaddrinfo(3) for more detail.

C Socket Error: "Name or service not known"

I'm trying to code a program in C that uses sockets to fetch webpages. My code currently prints successfully the HTML code at some webpages, but not all webpages. In the instances where it does not work I get the following error:
Name or service not known
Can someone please offer me a solution? The error occurs when executing getaddrinfo. I can't seem to figure it out after an extensive search for the answer. Thanks everyone!
My code is as follows:
#include <errno.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <err.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <stdarg.h>
/* "BSIZE" is the size of the buffer we use to read from the socket. */
#define BSIZE 0x1000
/* Quickie function to test for failures. It is actually better to use
a macro here, since a function like this results in unnecessary
function calls to things like "strerror". However, not every
version of C has variadic macros. */
static void fail (int test, const char * format, ...)
{
//printf("here in fail");
if (test) {
va_list args;
va_start (args, format);
vfprintf (stderr, format, args);
va_end (args);
exit (EXIT_FAILURE);
}
}
/* Get the web page and print it to standard output. */
static char * get_page (const char * host)
{
/* Output */
char * htmlCode;
const char * page = "momoe/";
/* "s" is the file descriptor of the socket. */
int s;
struct addrinfo hints, *res, *res0;
int error;
memset (&hints, 0, sizeof(hints));
/* Don't specify what type of internet connection. */
hints.ai_family = PF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
error = getaddrinfo (host, "http", & hints, & res0);
//printf("here 2");
fail (error, gai_strerror(error));
//printf("here3");
s = -1;
for (res = res0; res; res = res->ai_next) {
s = socket (res->ai_family, res->ai_socktype, res->ai_protocol);
fail (s < 0, "socket: %s\n", strerror (errno));
if (connect(s, res->ai_addr, res->ai_addrlen) < 0) {
fprintf (stderr, "connect: %s\n", strerror (errno));
close(s);
exit (EXIT_FAILURE);
}
break;
}
freeaddrinfo (res0);
if (s == -1) {
printf("Error with socket file ID");
return "Err";
}
/* "msg" is the request message that we will send to the
server. */
char * msg;
/* "format" is the format of the HTTP request we send to the web
server. */
const char * format =
"GET /%s HTTP/1.0\r\nHost: %s\r\nUser-Agent: fetch.c\r\n\r\n";
/* This holds return values from functions. */
int status;
/* I am using non-standard function "asprintf" for convenience. If
you don't have "asprintf", use "snprintf" with a fixed-size
buffer and check its return value against the length of the
buffer after the call. */
status = asprintf (& msg, format, page, host);
/* Check that "asprintf" succeeded. */
fail (status == -1 || ! msg, "asprintf failed.\n");
/* Send the request. */
status = send (s, msg, strlen (msg), 0);
/* Check it succeeded. The FreeBSD manual page doesn't mention
whether "send" sets errno, but
"http://pubs.opengroup.org/onlinepubs/009695399/functions/send.html"
claims it does. */
fail (status == -1, "send failed: %s\n", strerror (errno));
while (1) {
/* The number of bytes received. */
int bytes;
/* Our receiving buffer. */
char buf[BSIZE+10];
/* Get "BSIZE" bytes from "s". */
bytes = recvfrom (s, buf, BSIZE, 0, 0, 0);
/* Stop once there is nothing left to print. */
if (bytes == 0) {
break;
}
fail (bytes == -1, "%s\n", strerror (errno));
/* Nul-terminate the string before printing. */
buf[bytes] = '\0';
/* Add buffer text to output. */
//printf ("%s", buf);
strncat(htmlCode, buf, strlen(buf));
}
free (msg);
return htmlCode;
}
int main () {
/* Get one of the web pages here. */
char * host = "http://xkcd.com/352";
char * webPage;
//printf("\nhere\n");
webPage = get_page (host);
printf("Print HTML:\n\n%s", webPage);
return 0;
}
It looks like you're passing "http://xkcd.com/352" as the host name. You'll need to parse out the host part and only pass it, eg "xkcd.com"
There are mainly 3 issues in your code,
1. /* Output */
char * htmlCode;
You are not allocating memory for htmlCode variable anywhere in the program.
Ex: char htmlCode[1024*60];
2. const char * page = "momoe/";
Page name you given is not in the proper format.
Ex: const char* page = "Homepage.html"
3. char * host = "http://xkcd.com/352";
webPage = get_page (host);
The value in host variable is in wrong format.
Ex: char *host = "google.com"
You change the program and execute it. It'll work.

How to improve cmuSphinx's accuracy?

I want to use pocketShpinx to do some speech-to-text word. I have install sphinxbase and pocketSphinx. And download the acoustic model/langauge model/dictionary. Then I test the example code just like follows:
#include <pocketsphinx/pocketsphinx.h>
#include <stdio.h>
#include <stdlib.h>
#include "debug.h"
int main(int argc, char *argv[])
{
ps_decoder_t *ps;
cmd_ln_t *config;
FILE *fh;
int rv;
char const *hyp, *uttid;
int32 score;
config = cmd_ln_init(NULL, ps_args(), TRUE,
"-hmm", "/home/madper/speech/hub4opensrc.cd_continuous_8gau",
"-lm", "/home/madper/speech/language_model.arpaformat.DMP",
"-dict", "/home/madper/speech/cmudict/cmudict/sphinxdict/cmudict_SPHINX_40",
NULL);
if (config == NULL)
{
DBG (("cmd_ln_init() failed.\n"));
exit(1);
}
if ((ps = ps_init (config)) == NULL) /* init decoder */
{
DBG (("ps_init() failed.\n"));
exit(1 );
}
if ((fh = fopen("test.raw", "rb")) == NULL) /* open raw file */
{
DBG (("fopen() failed.\n"));
exit (1);
}
if ((rv = ps_decode_raw (ps, fh, "test", -1)) < 0 )
{
DBG (("ps_decode_raw() error!\n"));
exit (1);
}
if ((hyp = ps_get_hyp(ps, &score, &uttid)) == NULL)
{
DBG (("ps_get_hyp() failed!\n"));
exit (1);
}
printf ("Recognized: %s\n", hyp); /* this is what you say */
fclose(fh);
ps_free(ps);
return 0;
}
DBG is just a macro to print error message if defined DEBUG.
Then I write some code to record from mic use alsa. Like follows:
#define ALSA_PCM_NEW_HW_PARAMS_API
#include <alsa/asoundlib.h>
int main() {
long loops;
int rc;
int size;
snd_pcm_t *handle;
snd_pcm_hw_params_t *params;
unsigned int val;
int dir;
snd_pcm_uframes_t frames;
char *buffer;
/* Open PCM device for recording (capture). */
rc = snd_pcm_open(&handle, "default",
SND_PCM_STREAM_CAPTURE, 0);
if (rc < 0) {
fprintf(stderr,
"unable to open pcm device: %s\n",
snd_strerror(rc));
exit(1);
}
/* Allocate a hardware parameters object. */
snd_pcm_hw_params_alloca(&params);
/* Fill it in with default values. */
snd_pcm_hw_params_any(handle, params);
/* Set the desired hardware parameters. */
/* Interleaved mode */
snd_pcm_hw_params_set_access(handle, params,
SND_PCM_ACCESS_RW_INTERLEAVED);
/* Signed 16-bit little-endian format */
snd_pcm_hw_params_set_format(handle, params,
SND_PCM_FORMAT_S16_LE);
/* Two channels (stereo) */
snd_pcm_hw_params_set_channels(handle, params, 1);
/* 44100 bits/second sampling rate (CD quality) */
val = 16000;
snd_pcm_hw_params_set_rate_near(handle, params,
&val, &dir);
/* Set period size to 32 frames. */
frames = 16;
snd_pcm_hw_params_set_period_size_near(handle,
params, &frames, &dir);
/* Write the parameters to the driver */
rc = snd_pcm_hw_params(handle, params);
if (rc < 0) {
fprintf(stderr,
"unable to set hw parameters: %s\n",
snd_strerror(rc));
exit(1);
}
/* Use a buffer large enough to hold one period */
snd_pcm_hw_params_get_period_size(params,
&frames, &dir);
size = frames * 2; /* 2 bytes/sample, 2 channels */
buffer = (char *) malloc(size);
/* We want to loop for 5 seconds */
snd_pcm_hw_params_get_period_time(params,
&val, &dir);
loops = 2000000 / val;
while (loops > 0) {
loops--;
rc = snd_pcm_readi(handle, buffer, frames);
if (rc == -EPIPE) {
/* EPIPE means overrun */
fprintf(stderr, "overrun occurred\n");
snd_pcm_prepare(handle);
} else if (rc < 0) {
fprintf(stderr,
"error from read: %s\n",
snd_strerror(rc));
} else if (rc != (int)frames) {
fprintf(stderr, "short read, read %d frames\n", rc);
}
rc = write(1, buffer, size);
if (rc != size)
fprintf(stderr,
"short write: wrote %d bytes\n", rc);
}
snd_pcm_drain(handle);
snd_pcm_close(handle);
free(buffer);
return 0;
}
So, I record a raw file. Then do speech-to-test on that file. But the accuracy is very vert poor. Just like hello or go home will give me hotel or MHM MHM and so on. So what's wrong with these code?
I have read the faqs, should I use acoustic model adaptation to improve accuracy?
PS. I change stereo to mono. And the sound is strange. I can't understand what I said. So, what's wrong with it? This is that raw file test.raw
If you look at the first Q and A in http://cmusphinx.sourceforge.net/wiki/faq you will notice that the library assumes mono data.
You record in stereo.

Resources