Merge branch 'dev'

This commit is contained in:
Nils O. Selåsdal
2013-10-01 22:37:18 +02:00
15 changed files with 410 additions and 53 deletions
+119 -3
View File
@@ -17,57 +17,173 @@ enum UC_MBUF_FLAGS {
}; };
struct MBuf { struct MBuf {
/** prev/next pointer, user can use this for a linked list*/
struct MBuf *prev;
struct MBuf *next; struct MBuf *next;
/** Pointers the user can use to remember spots in
* the data. (these must either be NULL pointers or point into
* something in the buffer*/
uint8_t *p1; uint8_t *p1;
uint8_t *p2; uint8_t *p2;
uint8_t *p3; uint8_t *p3;
uint8_t *p4; uint8_t *p4;
/**Arbitary pointer user can associate with the mbuf*/
void *cookie; void *cookie;
uint32_t flags; uint32_t flags;
/** Total no of bytes from bufstart*/
uint32_t allocated; uint32_t allocated;
/** Start of the buffer*/
uint8_t *bufstart; uint8_t *bufstart;
/** Start of the data in the buffer*/
uint8_t *head; uint8_t *head;
/** End of the buffer (one byte past the data) */
uint8_t *tail; uint8_t *tail;
/** Internal data, if we allocate it inline */
uint8_t inline_data[0]; uint8_t inline_data[0];
}; };
/* Conventions: /**
* Concept:
* <--------- allocated ----------->
* <--- len -->
* +--------------------------------+
* |Headroom| Data |Tailroom |
* +--------------------------------+
* ^ ^ ^
* | | |
* | | tail
* | head
* bufstart
*
* Initially when empty, head == tail, and the length is 0.
* Data is added to the tail.
*
* If head == bufstart, there is no headroom
* if tail points one past the allocated space, there is no
* tailroom (the buffer is full)
*
* Conventions:
* push - prepend data to the buffer (in the head room part) * push - prepend data to the buffer (in the head room part)
* (move head to the left)
* pull - remove data from the beginning of the message. * pull - remove data from the beginning of the message.
* (move head to the right)
* put - Add data to the buffer. * put - Add data to the buffer.
* (move tail to the right)
*/
/** Allocate an mbuf with a length and headroom,
* the buffer will have the flag UC_MBUF_FL_MALLOC
* The total length of the buffer will be length+headroom
*
* @param len the initial length of the mbuf
* @param the initial headroom of the mbuf
* @return NULL if the allocation fails
*/ */
struct MBuf *uc_mbuf_new_hr(uint32_t len, uint32_t headroom); struct MBuf *uc_mbuf_new_hr(uint32_t len, uint32_t headroom);
/** As uc_mbuf_new_hr, but without any headroom*/
#define uc_mbuf_new(len) uc_mbuf_new_hr((len), 0) #define uc_mbuf_new(len) uc_mbuf_new_hr((len), 0)
/** Allocate an mbuf with a length and headroom,
* the buffer will have the flag UC_MBUF_FL_MALLOC_INLINE
* The total length of the buffer will be length+headroom
*
* @param len the initial length of the mbuf
* @param the initial headroom of the mbuf
* @return NULL if the allocation fails
*/
struct MBuf *uc_mbuf_new_inline_hr(uint32_t len, uint32_t headroom); struct MBuf *uc_mbuf_new_inline_hr(uint32_t len, uint32_t headroom);
/** As uc_mbuf_new_inline_hr, but without any headroom*/
#define uc_mbuf_new_inline(len) uc_mbuf_new_inline_hr((len), 0) #define uc_mbuf_new_inline(len) uc_mbuf_new_inline_hr((len), 0)
/** @param mbuf the mbuf to free. (passing NULL is a no-op)*/
void uc_mbuf_free(struct MBuf *mbuf); void uc_mbuf_free(struct MBuf *mbuf);
/** Create a new mbuf, with a copy of the data from the given
* mbuf. The new mbuf will have the same headroom as the old one,
* but no tailroom.
*
* @param mbuf mbuf to copy
*/
struct MBuf *uc_mbuf_copy_data(struct MBuf *mbuf); struct MBuf *uc_mbuf_copy_data(struct MBuf *mbuf);
/** Initialize an mbuf. This function is mostly used internally,
* but can be used to e.g. create an mbuf based on a local array
* (in which case UC_MBUF_FL_STATIC must be set), or other data
* whose memory is already allocated.
*
* The whole buffer must have len + headroom available data
*
* @param mbuf to initialise
* @param buf start of the buffer
* @param len length of the buffer (not including the headroom)
* @param headroom the headroom in the buffer
* @param flags The appropriate UC_MBUF_FLAGS
*/
void uc_mbuf_init(struct MBuf *mbuf, uint8_t *buf, uint32_t len, uint32_t headroom, uint32_t flags); void uc_mbuf_init(struct MBuf *mbuf, uint8_t *buf, uint32_t len, uint32_t headroom, uint32_t flags);
void uc_mbuf_zero(struct MBuf *mbuf);
void uc_mbuf_reset(struct MBuf *mbuf);
/** Zero out all the data in this mbuf, including the headroom
*
* @param mbuf mbuf to zero out
*/
void uc_mbuf_zero(struct MBuf *mbuf);
/**
* @return the length of the data in this mbuf
*/
static UC_INLINE uint32_t uc_mbuf_len(struct MBuf *mbuf) static UC_INLINE uint32_t uc_mbuf_len(struct MBuf *mbuf)
{ {
return (uint32_t)(mbuf->tail - mbuf->head); return (uint32_t)(mbuf->tail - mbuf->head);
} }
/**
* @return the length of the tailroom in this mbuf
*/
static UC_INLINE uint32_t uc_mbuf_tailroom(struct MBuf *mbuf) static UC_INLINE uint32_t uc_mbuf_tailroom(struct MBuf *mbuf)
{ {
return mbuf->allocated - (uint32_t)(mbuf->tail - mbuf->bufstart); return mbuf->allocated - (uint32_t)(mbuf->tail - mbuf->bufstart);
} }
/**
* @return the length of the headroom in this mbuf
*/
static inline uint32_t uc_mbuf_headroom(struct MBuf *mbuf) static inline uint32_t uc_mbuf_headroom(struct MBuf *mbuf)
{ {
return (uint32_t)(mbuf->head - mbuf->bufstart); return (uint32_t)(mbuf->head - mbuf->bufstart);
} }
/** Append data data to this buffer
* The returned pointer points at the end of the current
* data in the buffer, advancing the tail be size bytes .
* You need to insert the size bytes at in the returned pointer.
*
* @param size bytes to put in the buffer
* @return NULL if the mbuf does not have room for the given size
*/
uint8_t *uc_mbuf_put(struct MBuf *mbuf, uint32_t size); uint8_t *uc_mbuf_put(struct MBuf *mbuf, uint32_t size);
/** Prepend data to the buffer. The buffer needs to have enough
* headroom to allow this.
* The returned pointer points size bytes in front if the current
* data in the buffer, retreating the head pointer by size butes
* You need to insert the size bytes in the returned pointer.
*
* @oaram size bytes to prepend to the buffer
* @return NULL if the mbuf does not have enough headroom
*/
uint8_t *uc_mbuf_push(struct MBuf *mbuf, uint32_t size); uint8_t *uc_mbuf_push(struct MBuf *mbuf, uint32_t size);
/** Remove data from the buffer ("read" data from it)
* The returned pointer is the beginning of the data in the
* buffer, advancing the head by size bytes.
*
* @param size number of bytes to pull
* @return NULL if the buffer does not have at least size bytes
**/
uint8_t *uc_mbuf_pull(struct MBuf *mbuf, uint32_t size); uint8_t *uc_mbuf_pull(struct MBuf *mbuf, uint32_t size);
#undef UC_INLINE #undef UC_INLINE
+12
View File
@@ -83,6 +83,18 @@ void uc_strv_clear(struct UCStrv *strv);
*/ */
void uc_strv_destroy(struct UCStrv *strv); void uc_strv_destroy(struct UCStrv *strv);
/**
* Append all the elments from b to a
* If copy is 1, the appended elements will be copied when appended
*
* @param a destination UCStrv
* @param b source UCStrv
* @param copy 1 for making a copy of the string when appending it
* 0 to just append the same pointer in b to a
* @return 0 on success, != 0 if appending/allocation fails
*/
int uc_strv_append_all(struct UCStrv *a, struct UCStrv *b, int copy);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif
+3 -3
View File
@@ -46,14 +46,14 @@
//a 'zap' member inside a struct foo. //a 'zap' member inside a struct foo.
//give us the struct foo*: //give us the struct foo*:
//struct foo *f = CONTAINER_OF(p, struct foo, zap); //struct foo *f = CONTAINER_OF(p, struct foo, zap);
#define CONTAINER_OF(ptr, type, member) ({ \ #define UC_CONTAINER_OF(ptr, type, member) ({ \
typeof( ((type *)0)->member ) *__mptr = (ptr); \ typeof( ((type *)0)->member ) *__mptr = (ptr); \
(type *)((void *)(unsigned char *)__mptr - offsetof(type, member) ); }) (type *)((void *)(unsigned char *)__mptr - offsetof(type, member) ); })
//the void* cast is to suppress alignment warnings //the void* cast is to suppress alignment warnings
//Same as CONTAINER_OF, but for a const pointer to avoid gcc warnings.. //Same as UC_CONTAINER_OF, but for a const pointer to avoid gcc warnings..
#define CONST_CONTAINER_OF(ptr, type, member) ({ \ #define UC_CONST_CONTAINER_OF(ptr, type, member) ({ \
const typeof( ((const type *)0)->member ) *__mptr = (ptr); \ const typeof( ((const type *)0)->member ) *__mptr = (ptr); \
(const type *)((const void *)(const unsigned char *)__mptr - offsetof(const type, member) ); }) (const type *)((const void *)(const unsigned char *)__mptr - offsetof(const type, member) ); })
+2 -2
View File
@@ -32,7 +32,7 @@ static void uc_cached_clock_now(struct UCoreClock *uclock,
struct timeval *tv) struct timeval *tv)
{ {
struct UCoreCachedClock *cached_clock; struct UCoreCachedClock *cached_clock;
cached_clock = CONTAINER_OF(uclock, struct UCoreCachedClock, clock), cached_clock = UC_CONTAINER_OF(uclock, struct UCoreCachedClock, clock),
*tv = cached_clock->cache; *tv = cached_clock->cache;
} }
@@ -55,7 +55,7 @@ void uc_cached_clock_update(struct UCoreCachedClock *uclock)
static void uc_settable_clock_now(struct UCoreClock *uclock, struct timeval *tv) static void uc_settable_clock_now(struct UCoreClock *uclock, struct timeval *tv)
{ {
struct UCoreSettableClock *cached_clock; struct UCoreSettableClock *cached_clock;
cached_clock = CONTAINER_OF(uclock, struct UCoreSettableClock, clock), cached_clock = UC_CONTAINER_OF(uclock, struct UCoreSettableClock, clock),
*tv = cached_clock->now; *tv = cached_clock->now;
} }
+2
View File
@@ -86,11 +86,13 @@ struct MBuf *uc_mbuf_new_inline_hr(uint32_t len, uint32_t headroom)
void uc_mbuf_free(struct MBuf *mbuf) void uc_mbuf_free(struct MBuf *mbuf)
{ {
if (mbuf != NULL) {
if (mbuf->flags & (UC_MBUF_FL_MALLOC | UC_MBUF_FL_MALLOC_BUF)) if (mbuf->flags & (UC_MBUF_FL_MALLOC | UC_MBUF_FL_MALLOC_BUF))
free(mbuf->bufstart); free(mbuf->bufstart);
if (mbuf->flags & (UC_MBUF_FL_MALLOC | UC_MBUF_FL_MALLOC_INLINE)) if (mbuf->flags & (UC_MBUF_FL_MALLOC | UC_MBUF_FL_MALLOC_INLINE))
free(mbuf); free(mbuf);
}
} }
void uc_mbuf_zero(struct MBuf *mbuf) void uc_mbuf_zero(struct MBuf *mbuf)
+27 -2
View File
@@ -29,7 +29,8 @@ int uc_strv_expand(struct UCStrv *strv)
int rc = 0; int rc = 0;
if (strv->cnt >= strv->allocated) { if (strv->cnt >= strv->allocated) {
rc = uc_strv_grow(strv, 1); //make some extra room
rc = uc_strv_grow(strv, 4);
} }
return rc; return rc;
@@ -81,7 +82,6 @@ int uc_strv_null_terminate(struct UCStrv *strv)
} }
strv->strings[strv->cnt] = NULL; strv->strings[strv->cnt] = NULL;
strv->cnt++;
return 0; return 0;
} }
@@ -105,3 +105,28 @@ void uc_strv_destroy(struct UCStrv *strv)
strv->strings = NULL; strv->strings = NULL;
} }
int uc_strv_append_all(struct UCStrv *a, struct UCStrv *b, int copy)
{
size_t i;
int rc;
rc = uc_strv_grow(a, a->allocated + b->cnt);
if (rc != 0) {
return rc;
}
for (i = 0; i < b->cnt; i++) {
if (copy) {
rc = uc_strv_append(a, b->strings[i]);
} else {
rc = uc_strv_append_nocopy(a, b->strings[i]);
}
if (rc != 0) {
return rc;
}
}
return 0;
}
+17 -7
View File
@@ -57,7 +57,9 @@ int uc_thread_queue_init(struct uc_threadqueue *queue, long max_elements)
return rc; return rc;
} }
int uc_thread_queue_tryadd(struct uc_threadqueue *queue, const struct timespec *timeout, struct uc_threadmsg *msg) int uc_thread_queue_tryadd(struct uc_threadqueue *queue,
const struct timespec *timeout,
struct uc_threadmsg *msg)
{ {
int rc = 0; int rc = 0;
struct timespec abstimeout; struct timespec abstimeout;
@@ -81,7 +83,8 @@ int uc_thread_queue_tryadd(struct uc_threadqueue *queue, const struct timespec *
if(timeout->tv_sec == 0 && timeout->tv_nsec == 0) { if(timeout->tv_sec == 0 && timeout->tv_nsec == 0) {
rc = ETIMEDOUT; rc = ETIMEDOUT;
} else { } else {
rc = pthread_cond_timedwait(&queue->write_cond, &queue->mutex, &abstimeout); rc = pthread_cond_timedwait(&queue->write_cond, &queue->mutex,
&abstimeout);
} }
} else { } else {
@@ -127,7 +130,9 @@ int uc_thread_queue_tryadd(struct uc_threadqueue *queue, const struct timespec *
} }
int uc_thread_queue_tryget(struct uc_threadqueue *queue, const struct timespec *timeout, struct uc_threadmsg **msg) int uc_thread_queue_tryget(struct uc_threadqueue *queue,
const struct timespec *timeout,
struct uc_threadmsg **msg)
{ {
int rc = 0; int rc = 0;
struct timespec abstimeout; struct timespec abstimeout;
@@ -153,7 +158,8 @@ int uc_thread_queue_tryget(struct uc_threadqueue *queue, const struct timespec *
if(timeout->tv_sec == 0 && timeout->tv_nsec == 0) { if(timeout->tv_sec == 0 && timeout->tv_nsec == 0) {
rc = ETIMEDOUT; rc = ETIMEDOUT;
} else { } else {
rc = pthread_cond_timedwait(&queue->read_cond, &queue->mutex, &abstimeout); rc = pthread_cond_timedwait(&queue->read_cond, &queue->mutex,
&abstimeout);
} }
} else { } else {
pthread_cond_wait(&queue->read_cond, &queue->mutex); pthread_cond_wait(&queue->read_cond, &queue->mutex);
@@ -192,17 +198,20 @@ int uc_thread_queue_tryget(struct uc_threadqueue *queue, const struct timespec *
return 0; return 0;
} }
static void uc_thread_queue_walk_unlocked(struct uc_threadqueue *queue, uc_thread_queue_walk_func walk_func) static void uc_thread_queue_walk_unlocked(struct uc_threadqueue *queue,
uc_thread_queue_walk_func walk_func)
{ {
struct uc_threadmsg *p; struct uc_threadmsg *p;
struct uc_threadmsg *next; struct uc_threadmsg *next;
for(p = queue->first; p; p = next) { for(p = queue->first; p; p = next) {
next = p->next; next = p->next;
walk_func(p); walk_func(p);
} }
} }
int uc_thread_queue_walk(struct uc_threadqueue *queue, uc_thread_queue_walk_func walk_func) int uc_thread_queue_walk(struct uc_threadqueue *queue,
uc_thread_queue_walk_func walk_func)
{ {
if (queue == NULL || !walk_func) { if (queue == NULL || !walk_func) {
return EINVAL; return EINVAL;
@@ -217,7 +226,8 @@ int uc_thread_queue_walk(struct uc_threadqueue *queue, uc_thread_queue_walk_func
return 0; return 0;
} }
int uc_thread_queue_destroy(struct uc_threadqueue *queue, uc_thread_queue_walk_func free_func) int uc_thread_queue_destroy(struct uc_threadqueue *queue,
uc_thread_queue_walk_func free_func)
{ {
int rc; int rc;
+2 -2
View File
@@ -6,8 +6,8 @@
static int timers_cmp(const RBNode *a_, const RBNode *b_) static int timers_cmp(const RBNode *a_, const RBNode *b_)
{ {
const struct UCTimer *a = CONST_CONTAINER_OF(a_, struct UCTimer, rb_node); const struct UCTimer *a = UC_CONST_CONTAINER_OF(a_, struct UCTimer, rb_node);
const struct UCTimer *b = CONST_CONTAINER_OF(b_, struct UCTimer, rb_node); const struct UCTimer *b = UC_CONST_CONTAINER_OF(b_, struct UCTimer, rb_node);
if (timercmp(&a->timeout, &b->timeout, <)) { if (timercmp(&a->timeout, &b->timeout, <)) {
return -1; return -1;
+146
View File
@@ -0,0 +1,146 @@
#include <stdio.h>
#include <time.h>
#include <stdlib.h>
#include <string.h>
#include <ortp/ortp.h>
#include <ucore/iomux.h>
#include <ucore/utils.h>
#include <ucore/string.h>
struct IOMux *mux;
#define errx(x, ...) do { fprintf(stderr, x, __VA_ARGS__); exit(1); } while(0)
struct RTPSender {
FILE *file;
char remote_ip[48];
uint16_t remote_port;
struct UCTimer timer;
uint32_t ts;
struct timespec last_ts;
RtpSession *rtp_sess;
RtpProfile *rtp_profile;
int accum_diff;
uint8_t frame[160];
};
//returns microsec
int diffts(const struct timespec *a, struct timespec *b)
{
struct timespec diff;
diff.tv_sec = b->tv_sec - a->tv_sec;
diff.tv_nsec = b->tv_nsec - a->tv_nsec;
if (diff.tv_nsec < 0) {
diff.tv_sec--;
diff.tv_nsec += 1000000000;
}
return (int) (diff.tv_sec * 1000 + (diff.tv_nsec + 500)/1000);
}
void timer_cb(struct UCTimers *timers, struct UCTimer *timer)
{
struct RTPSender *s = UC_CONTAINER_OF(timer, struct RTPSender, timer);
int rc;
ssize_t r;
struct timespec ts;
int diff;
int adjust;
clock_gettime(CLOCK_MONOTONIC, &ts);
rc = rtp_session_send_with_ts(s->rtp_sess,s->frame, sizeof s->frame, s->ts);
if(rc < sizeof s->frame) {
printf("Error, short send of %d bytes\n", rc);
}
s->ts += 160;
r = fread(s->frame,1, sizeof s->frame, s->file);
if (r <= 0) {
rtp_session_bye(s->rtp_sess, "Finished");
return;
}
diff = diffts(&s->last_ts, &ts);
diff -= 20000;
s->accum_diff += diff;
if (s->accum_diff > 500)
adjust = -1000;
else if (s->accum_diff < -500)
adjust = 1000;
else
adjust = s->accum_diff;
if (s->accum_diff >= 20000 || s->accum_diff <= -20000) {
s->ts += 160;
printf("Skew ! accum_diff %d\n", s->accum_diff);
s->accum_diff -= 20000;
}
uc_timers_add(iomux_get_timers(mux), &s->timer, 0, 20 * 1000 + adjust);
s->last_ts = ts;
}
void init_sender(FILE* file, const char *remote_ip, uint16_t remote_port)
{
struct RTPSender *s = calloc(1, sizeof *s);
RtpSession *rtp_sess = rtp_session_new(RTP_SESSION_SENDONLY);
RtpProfile *rtp_prof = rtp_profile_new("pcmu8000");
rtp_profile_set_payload(rtp_prof, 0, &payload_type_pcmu8000);
rtp_session_set_profile(rtp_sess, rtp_prof);
//rtp_session_set_local_addr("192.168.1.55", 0);
rtp_session_set_remote_addr(rtp_sess, remote_ip, remote_port);
rtp_session_set_blocking_mode(rtp_sess, FALSE);
s->file = file;
strcpy(s->remote_ip, remote_ip);
s->remote_port = remote_port;
s->rtp_sess = rtp_sess;
s->rtp_profile = rtp_prof;
s->timer.callback = timer_cb;
clock_gettime(CLOCK_MONOTONIC, &s->last_ts);
uc_timers_add(iomux_get_timers(mux), &s->timer, 0, 20000);
}
int main(int argc, char *argv[])
{
mux = iomux_create(IOMUX_TYPE_DEFAULT);
FILE *file;
if(argc != 4) {
puts("Specify a file name, remote IP and remote port");
return 1;
}
if(strcmp(argv[1], "-") == 0) {
file = stdin;
} else {
file = fopen(argv[1], "rb");
if(file == NULL) {
perror("Cannot open file");
return 1;
}
}
ortp_init();
ortp_set_log_level_mask(ORTP_DEBUG| ORTP_MESSAGE| ORTP_WARNING| ORTP_ERROR|ORTP_FATAL);
init_sender(file ,argv[2], atoi(argv[3]));
iomux_run(mux);
fclose(file);
ortp_exit();
return 0;
}
//compile:
// gcc -Wall -g -O `pkg-config --cflags --libs ortp` ortp-send-simple.c
+1 -1
View File
@@ -25,7 +25,7 @@ START_TEST (test_container_of)
}; };
struct Inner *innerp = &outer.inner; struct Inner *innerp = &outer.inner;
struct Outer *outerp = CONTAINER_OF(innerp, struct Outer, inner); struct Outer *outerp = UC_CONTAINER_OF(innerp, struct Outer, inner);
fail_if(outerp != &outer); fail_if(outerp != &outer);
+3 -3
View File
@@ -33,9 +33,7 @@ static suite_func suites[] = {
read_file_suite, read_file_suite,
pack_suite, pack_suite,
logging_suite, logging_suite,
threadqueue_suite,
buffer_suite, buffer_suite,
clock_suite,
seq_suite, seq_suite,
sat_math_suite, sat_math_suite,
timers_suite, timers_suite,
@@ -43,7 +41,9 @@ static suite_func suites[] = {
human_bytesz_suite, human_bytesz_suite,
dbuf_suite, dbuf_suite,
sprintb_suite, sprintb_suite,
strv_suite strv_suite,
clock_suite,
threadqueue_suite
}; };
int int
+52
View File
@@ -1,5 +1,6 @@
#include <check.h> #include <check.h>
#include <string.h> #include <string.h>
#include <stdlib.h>
#include <ucore/strvec.h> #include <ucore/strvec.h>
@@ -67,12 +68,61 @@ START_TEST (test_strv_null_terminate)
rc = uc_strv_null_terminate(&strv); rc = uc_strv_null_terminate(&strv);
fail_if(rc != 0); fail_if(rc != 0);
fail_if(strv.cnt != 1); //shouldn't increase .cnt
fail_if(strv.strings[strv.cnt] != NULL); fail_if(strv.strings[strv.cnt] != NULL);
uc_strv_destroy(&strv); uc_strv_destroy(&strv);
END_TEST END_TEST
START_TEST (test_strv_append_all_copy)
struct UCStrv src;
struct UCStrv dst;
int rc;
uc_strv_init(&src);
uc_strv_init(&dst);
uc_strv_append(&dst, "string1");
uc_strv_append(&src, "string2");
uc_strv_append(&src, "string3");
rc = uc_strv_append_all(&dst, &src, 1);
fail_if(rc != 0);
fail_if(dst.cnt != 3);
ck_assert_str_eq("string1", dst.strings[0]);
ck_assert_str_eq("string2", dst.strings[1]);
ck_assert_str_eq("string3", dst.strings[2]);
uc_strv_destroy(&src);
uc_strv_destroy(&dst);
END_TEST
START_TEST (test_strv_append_all_nocopy)
struct UCStrv src;
struct UCStrv dst;
int rc;
uc_strv_init(&src);
uc_strv_init(&dst);
uc_strv_append(&dst, "string1");
uc_strv_append(&src, "string2");
uc_strv_append(&src, "string3");
rc = uc_strv_append_all(&dst, &src, 0);
fail_if(rc != 0);
fail_if(dst.cnt != 3);
ck_assert_str_eq("string1", dst.strings[0]);
ck_assert_str_eq("string2", dst.strings[1]);
ck_assert_str_eq("string3", dst.strings[2]);
uc_strv_destroy(&dst);
free(src.strings);
END_TEST
Suite *strv_suite(void) Suite *strv_suite(void)
{ {
@@ -83,6 +133,8 @@ Suite *strv_suite(void)
tcase_add_test(tc, test_strv_clear); tcase_add_test(tc, test_strv_clear);
tcase_add_test(tc, test_strv_nocopy); tcase_add_test(tc, test_strv_nocopy);
tcase_add_test(tc, test_strv_null_terminate); tcase_add_test(tc, test_strv_null_terminate);
tcase_add_test(tc, test_strv_append_all_copy);
tcase_add_test(tc, test_strv_append_all_nocopy);
suite_add_tcase(s, tc); suite_add_tcase(s, tc);
+16 -22
View File
@@ -164,37 +164,31 @@ START_TEST (test_timers_add_remove)
struct UCoreSettableClock clk; struct UCoreSettableClock clk;
struct TimerTest tt; struct TimerTest tt;
struct UCTimers timers; struct UCTimers timers;
struct UCTimer timer1; struct UCTimer timer[1023];
struct UCTimer timer2;
struct UCTimer timer3;
struct UCTimer timer4;
struct timeval first; struct timeval first;
size_t i;
int toggle = 5;
common_init(&clk, &tt, &timers, &timer1); common_init(&clk, &tt, &timers, &timer[0]);
memset(&timer2, 0, sizeof timer2); memset(&timer, 0, sizeof timer);
memset(&timer3, 0, sizeof timer2); for (i = 0; i < sizeof timer/sizeof timer[0]; i++) {
memset(&timer4, 0, sizeof timer2); timer[i].callback = timer_test_cb_add;
timer1.callback = timer_test_cb_add; uc_timers_add(&timers, &timer[i], toggle + i , 0);
timer2.callback = timer_test_cb_add; if (i > 5) //just to add timeouts non-ascending order
timer3.callback = timer_test_cb_add; toggle = 5 - toggle;
timer4.callback = timer_test_cb_add; }
uc_timers_add(&timers, &timer1, 10, 0);
uc_timers_add(&timers, &timer2, 5 , 0);
uc_timers_add(&timers, &timer3, 15, 1);
uc_timers_add(&timers, &timer4, 15, 1);
fail_if(uc_timers_first(&timers, &first) != 0); fail_if(uc_timers_first(&timers, &first) != 0);
fail_if(first.tv_sec != TEST_TIMER_START + 5); fail_if(first.tv_sec != TEST_TIMER_START + 5);
fail_if(first.tv_usec != 0); fail_if(first.tv_usec != 0);
fail_if(uc_timers_count(&timers) != 4); fail_if(uc_timers_count(&timers) != sizeof timer/sizeof timer[0]);
for (i = 0; i < sizeof timer/sizeof timer[0]; i++) {
uc_timers_remove(&timers, &timer[i]);
}
uc_timers_remove(&timers, &timer1);
uc_timers_remove(&timers, &timer2);
uc_timers_remove(&timers, &timer3);
uc_timers_remove(&timers, &timer4);
fail_if(uc_timers_count(&timers) != 0); fail_if(uc_timers_count(&timers) != 0);
fail_if(uc_timers_first(&timers, &first) == 0); fail_if(uc_timers_first(&timers, &first) == 0);
+1 -1
View File
@@ -22,7 +22,7 @@ void t2_cb(struct UCTimers *timers, struct UCTimer *timer)
void mystruct1_cb(struct UCTimers *timers, struct UCTimer *timer) void mystruct1_cb(struct UCTimers *timers, struct UCTimer *timer)
{ {
struct MyStruct *mystruct = CONTAINER_OF(timer, struct MyStruct, timer); struct MyStruct *mystruct = UC_CONTAINER_OF(timer, struct MyStruct, timer);
TRACEF("MyStruct1 timer: %s\n", mystruct->str); TRACEF("MyStruct1 timer: %s\n", mystruct->str);
uc_timers_add(timers, timer, 1, 0); uc_timers_add(timers, timer, 1, 0);
+2 -2
View File
@@ -70,7 +70,7 @@ void peer_do_state(struct HBPeer *peer, enum PeerEvent event);
void peer_timer_cb(struct UCTimers *timers, struct UCTimer *timer) void peer_timer_cb(struct UCTimers *timers, struct UCTimer *timer)
{ {
struct HBPeer *peer = CONTAINER_OF(timer, struct HBPeer, timer); struct HBPeer *peer = UC_CONTAINER_OF(timer, struct HBPeer, timer);
struct HBContext *ctx = timer->cookie_ptr; struct HBContext *ctx = timer->cookie_ptr;
time_t now; time_t now;
@@ -181,7 +181,7 @@ void peer_received(struct HBPeer *peer)
void hb_read(struct IOMux *mux, struct IOMuxFD *fd, unsigned int event) void hb_read(struct IOMux *mux, struct IOMuxFD *fd, unsigned int event)
{ {
struct HBContext *ctx = CONTAINER_OF(fd, struct HBContext, sock_fd); struct HBContext *ctx = UC_CONTAINER_OF(fd, struct HBContext, sock_fd);
ssize_t rc; ssize_t rc;
struct sockaddr_in peer_addr; struct sockaddr_in peer_addr;
socklen_t peer_len = sizeof peer_addr; socklen_t peer_len = sizeof peer_addr;