int session_issue_call (Sess *sess, Call *call) { Call_Private_Data *cpriv; Sess_Private_Data *priv; struct Conn_Info *ci; int i; priv = SESS_PRIVATE_DATA (sess); cpriv = CALL_PRIVATE_DATA (call); cpriv->sess = sess; for (i = 0; i < param.max_conns; ++i) { ci = priv->conn_info + i; if (ci->num_pending < param.max_piped) { ++ci->num_pending; ci->call[ci->wr] = call; call_inc_ref (call); ci->wr = (ci->wr + 1) % MAX_PIPED; send_calls (sess, ci); return 0; } } fprintf (stderr, "%s.session_issue_call: too many calls pending!\n" "\tIncrease --max-connections and/or --max-piped-calls.\n", prog_name); exit (1); }
static void call_recv_hdr (Event_Type et, Object *obj, Any_Type regarg, Any_Type callarg) { Call_Private_Data *cpriv; Sess_Private_Data *priv; struct iovec *line; Call *call; Sess *sess; char *hdr; assert (et == EV_CALL_RECV_HDR && object_is_call (obj)); call = (Call *) obj; cpriv = CALL_PRIVATE_DATA (call); sess = session_get_sess_from_call (call); priv = SESS_PRIVATE_DATA (sess); line = callarg.vp; hdr = line->iov_base; switch (tolower (hdr[0])) { case 'c': if (line->iov_len >= 23 && strncasecmp (hdr + 1, "ontent-type: text/html", 22) == 0) cpriv->state = P_HTML; break; case 'l': if (line->iov_len > 10 && strncasecmp (hdr + 1, "ocation: ", 9) == 0) fetch_uri (sess, priv, cpriv, hdr + 10, line->iov_len - 10); break; } }
static void sess_destroyed (Event_Type et, Object *obj, Any_Type regarg, Any_Type callarg) { Sess_Private_Data *priv; struct Conn_Info *ci; Sess *sess; int i, j, rd; assert (et == EV_SESS_DESTROYED && object_is_sess (obj)); sess = (Sess *) obj; priv = SESS_PRIVATE_DATA (sess); for (i = 0; i < param.max_conns; ++i) { ci = priv->conn_info + i; if (ci->conn) core_close (ci->conn); rd = ci->rd; for (j = 0; j < ci->num_pending; ++j) { call_dec_ref (ci->call[rd]); rd = (rd + 1) % MAX_PIPED; } } }
static void call_issue (Event_Type et, Object *obj, Any_Type regarg, Any_Type callarg) { Call_Private_Data *cpriv; Sess_Private_Data *priv; Sess *sess; Call *call; assert (et == EV_CALL_ISSUE && object_is_call (obj)); call = (Call *) obj; cpriv = CALL_PRIVATE_DATA (call); if (cpriv->cookie_present) /* don't do anything if cookie has been set already */ return; sess = session_get_sess_from_call (call); priv = SESS_PRIVATE_DATA (sess); if (priv->cookie_len > 0) { if (DBG > 1) fprintf (stderr, "call_issue.%ld: inserting `%s'\n", call->id, priv->cookie); cpriv->cookie_present = 1; memcpy (cpriv->cookie, priv->cookie, priv->cookie_len + 1); call_append_request_header (call, cpriv->cookie, priv->cookie_len); } }
/* Create a new session. */ static int sess_create (Any_Type arg) { Sess_Private_Data *priv; Sess *sess; if (num_sessions_generated++ >= param.wsess.num_sessions) return -1; sess = sess_new (); if (!sess) return 1; priv = SESS_PRIVATE_DATA (sess); priv->num_calls_target = param.burst_len; issue_calls (sess, SESS_PRIVATE_DATA (sess)); return 0; }
static void user_think_time_expired(struct Timer *t, Any_Type arg) { Sess *sess = arg.vp; Sess_Private_Data *priv; assert(object_is_sess(sess)); priv = SESS_PRIVATE_DATA (sess); priv->timer = 0; issue_calls(sess, priv); }
static void sess_created (Event_Type et, Object *obj, Any_Type regarg, Any_Type callarg) { Sess_Private_Data *priv; Sess *sess; assert (et == EV_SESS_NEW && object_is_sess (obj)); sess = (Sess *) obj; priv = SESS_PRIVATE_DATA (sess); priv->birth_time = timer_now (); }
static void conn_connected (Event_Type et, Object *obj, Any_Type regarg, Any_Type callarg) { Sess_Private_Data *priv; Sess *sess; Conn *conn; assert (et == EV_CONN_CONNECTED && object_is_conn (obj)); conn = (Conn *) obj; sess = session_get_sess_from_conn (conn); priv = SESS_PRIVATE_DATA (sess); ++priv->num_conns; }
static void call_done (Event_Type et, Object *obj, Any_Type regarg, Any_Type callarg) { Sess_Private_Data *priv; Sess *sess; Call *call; assert (et == EV_CALL_RECV_STOP && object_is_call (obj)); call = (Call *) obj; sess = session_get_sess_from_call (call); priv = SESS_PRIVATE_DATA (sess); ++priv->num_calls_completed; }
size_t session_current_qlen (Sess *sess) { Sess_Private_Data *priv; size_t num_pending = 0; int i; priv = SESS_PRIVATE_DATA (sess); for (i = 0; i < param.max_conns; ++i) num_pending += priv->conn_info[i].num_pending; return num_pending; }
/* Create a new session. */ static int sess_create (Any_Type arg) { Sess *sess; if (num_sessions_generated++ >= param.wsesspage.num_sessions) return -1; sess = sess_new (); if (!sess) return 1; issue_calls (sess, SESS_PRIVATE_DATA (sess)); return 0; }
static void sess_destroyed (Event_Type et, Object *obj, Any_Type regarg, Any_Type callarg) { Sess_Private_Data *priv; Sess *sess; Time now; assert (et == EV_SESS_DESTROYED && object_is_sess (obj)); sess = (Sess *) obj; priv = SESS_PRIVATE_DATA (sess); now=timer_now(); if(now>=end)core_exit(); if (++num_sessions_destroyed >= param.wsessreq.num_sessions) core_exit (); }
static void sess_destroyed (Event_Type et, Object *obj, Any_Type regarg, Any_Type callarg) { size_t old_size, new_size; Sess_Private_Data *priv; Sess *sess; Time delta, now = timer_now (); assert (et == EV_SESS_DESTROYED && object_is_sess (obj)); sess = (Sess *) obj; priv = SESS_PRIVATE_DATA (sess); delta = (now - priv->birth_time); if (sess->failed) { ++st.num_failed; st.failtime_sum += delta; } else { st.num_conns += priv->num_conns; ++st.num_completed_since_last_sample; ++st.num_completed; st.lifetime_sum += delta; } if (priv->num_calls_completed > st.longest_session) { st.longest_session = priv->num_calls_completed; if (st.longest_session >= st.len_hist_alloced) { old_size = st.len_hist_alloced*sizeof (st.len_hist[0]); st.len_hist_alloced = st.longest_session + 16; new_size = st.len_hist_alloced*sizeof (st.len_hist[0]); st.len_hist = realloc (st.len_hist, new_size); if (!st.len_hist) { fprintf (stderr, "%s.sess_stat: Out of memory\n", prog_name); exit (1); } memset ((char *) st.len_hist + old_size, 0, new_size - old_size); } } ++st.len_hist[priv->num_calls_completed]; }
static void call_destroyed (Event_Type et, Object *obj, Any_Type regarg, Any_Type callarg) { Call_Private_Data *cpriv; Sess_Private_Data *priv; Any_Type arg; Sess *sess; Call *call; assert (et == EV_CALL_DESTROYED && object_is_call (obj)); call = (Call *) obj; cpriv = CALL_PRIVATE_DATA (call); sess = session_get_sess_from_call (call); priv = SESS_PRIVATE_DATA (sess); if (cpriv->to_free) { free (cpriv->to_free); cpriv->to_free = 0; } ++priv->num_destroyed; if (sess->failed) return; if (priv->uri_list) /* there are some queued URI's which we may be able to issue now */ issue_calls (sess, priv); else if (priv->num_destroyed >= priv->num_created) { /* we're done with this burst */ if (++priv->num_reqs_completed >= param.wsesspage.num_reqs) /* we're done with this session */ sess_dec_ref (sess); else { /* schedule the user-think-time timer */ priv->num_created = 0; assert (!priv->timer); arg.vp = sess; priv->timer = timer_schedule (user_think_time_expired, arg, param.wsesspage.think_time); } } }
static void sess_destroyed(Event_Type et, Object *obj, Any_Type regarg, Any_Type callarg) { Sess_Private_Data *priv; Sess *sess; assert(et == EV_SESS_DESTROYED && object_is_sess(obj)); sess = (Sess *) obj; priv = SESS_PRIVATE_DATA (sess); if (priv->timer) { timer_cancel(priv->timer); priv->timer = 0; } if (++num_sessions_destroyed >= param.wsesslog.num_sessions) core_exit(); }
static void call_recv_hdr (Event_Type et, Object *obj, Any_Type regarg, Any_Type callarg) { char *hdr, *start, *end; Sess_Private_Data *priv; size_t len; struct iovec *line; Sess *sess; Call *call; assert (et == EV_CALL_RECV_HDR && object_is_call (obj)); call = (Call *) obj; sess = session_get_sess_from_call (call); priv = SESS_PRIVATE_DATA (sess); line = callarg.vp; hdr = line->iov_base; if (tolower (hdr[0]) == 's' && line->iov_len > 12 && strncasecmp (hdr + 1, "et-cookie: ", 11) == 0) { /* munch time! */ start = hdr + 12; end = strchr (start, ';'); if (!end) end = hdr + line->iov_len; len = end - start; if (DBG > 0 && priv->cookie_len > 0) fprintf (stderr, "%s: can't handle more than one " "cookie at a time, replacing existing one\n", prog_name); if (len + 10 >= MAX_COOKIE_LEN) { fprintf (stderr, "%s.sess_cookie: truncating cookie to %d bytes\n", prog_name, MAX_COOKIE_LEN - 11); len = MAX_COOKIE_LEN - 11; } memcpy (priv->cookie, "Cookie: ", 8); memcpy (priv->cookie + 8, start, len); memcpy (priv->cookie + 8 + len, "\r\n", 2); priv->cookie[10 + len] = '\0'; priv->cookie_len = len + 10; if (DBG > 0) fprintf (stderr, "%s: got cookie `%s'\n", prog_name, start); } }
static void call_destroyed (Event_Type et, Object *obj, Any_Type regarg, Any_Type callarg) { Any_Type arg; Sess *sess; Call *call; Sess_Private_Data *priv; assert (et == EV_CALL_DESTROYED && object_is_call (obj)); call = (Call *) obj; sess = session_get_sess_from_call (call); priv = SESS_PRIVATE_DATA (sess); ++priv->num_calls_destroyed; if (priv->num_calls_destroyed >= param.wsess.num_calls) { /* we're done with this session */ if (!sess->failed) sess_dec_ref (sess); } else if (priv->num_calls_in_this_burst < param.burst_len) /* now that we received the reply to the first call in this burst, create the remaining calls */ issue_calls (sess, priv); else if (priv->num_calls_destroyed >= priv->num_calls_target) { /* we're done with this burst---schedule the user-think-time timer */ priv->num_calls_in_this_burst = 0; priv->num_calls_target += param.burst_len; assert (!priv->timer); arg.vp = sess; priv->timer = timer_schedule (user_think_time_expired, arg, param.wsess.think_time); } }
static void call_recv_data (Event_Type et, Object *obj, Any_Type regarg, Any_Type callarg) { Call_Private_Data *cpriv; Sess_Private_Data *priv; const char *cp, *end; struct iovec *line; Sess *sess; Call *call; int ch; assert (et == EV_CALL_RECV_DATA && object_is_call (obj)); call = (Call *) obj; cpriv = CALL_PRIVATE_DATA (call); sess = session_get_sess_from_call (call); priv = SESS_PRIVATE_DATA (sess); if (cpriv->state == P_INITIAL) return; /* not an html object */ line = callarg.vp; cp = line->iov_base; end = cp + line->iov_len; while (cp < end) { ch = *cp++; switch (cpriv->state) { case P_INITIAL: break; case P_HTML: cpriv->buf_len = 0; if (ch == '<') cpriv->state = P_CMD; break; case P_CMD: if (isspace (ch) || ch == '=') { if (cpriv->buf_len > 0) { if (DBG > 3) fprintf (stderr, "found command `%.*s'\n", cpriv->buf_len, cpriv->buf); if (cpriv->buf_len == 3 && strcmp (cpriv->buf, "!--") == 0) cpriv->state = P_DASH_ONE; else if (cpriv->buf_len == 5 && strncasecmp (cpriv->buf, "frame", 5) == 0) cpriv->state = P_SRC; else if (cpriv->buf_len == 6 && strncasecmp (cpriv->buf, "iframe", 6) == 0) cpriv->state = P_SRC; else if (cpriv->buf_len == 6 && strncasecmp (cpriv->buf, "data", 6) == 0) cpriv->state = P_DATA; else if (cpriv->buf_len == 3 && strncasecmp (cpriv->buf, "img", 3) == 0) cpriv->state = P_SRC; cpriv->buf_len = 0; } else cpriv->state = P_HTML; } else if (ch == '>') cpriv->state = P_HTML; else if (cpriv->buf_len < sizeof (cpriv->buf)) cpriv->buf[cpriv->buf_len++] = ch; break; case P_DASH_ONE: if (ch == '-') cpriv->state = P_DASH_TWO; break; case P_DASH_TWO: cpriv->state = (ch == '-') ? P_RANGLE : P_DASH_ONE; break; case P_RANGLE: if (ch == '>') cpriv->state = P_HTML; break; case P_SRC: if (ch == '>') cpriv->state = P_HTML; else { cpriv->buf[cpriv->buf_len++] = ch; if (cpriv->buf_len == 4) { if (strncasecmp (cpriv->buf, "src=", 4) == 0) { cpriv->state = P_LQUOTE; cpriv->buf_len = 0; } else { memcpy (cpriv->buf, cpriv->buf + 1, 3); cpriv->buf_len = 3; } } } break; case P_DATA: if (ch == '>') cpriv->state = P_HTML; else { cpriv->buf[cpriv->buf_len++] = ch; if (cpriv->buf_len == 5) { if (strncasecmp (cpriv->buf, "data=", 5) == 0) { cpriv->state = P_LQUOTE; cpriv->buf_len = 0; } else { memcpy (cpriv->buf, cpriv->buf + 1, 4); cpriv->buf_len = 4; } } } break; case P_LQUOTE: if (ch == '"') cpriv->state = P_QUOTED_URI; else if (!isspace (ch)) { cpriv->state = P_NAKED_URI; cpriv->buf[cpriv->buf_len++] = ch; } break; case P_NAKED_URI: case P_QUOTED_URI: if ((cpriv->state == P_QUOTED_URI && ch == '"') || (cpriv->state == P_NAKED_URI && isspace (ch))) { cpriv->buf[cpriv->buf_len] = '\0'; fetch_uri (sess, priv, cpriv, cpriv->buf, cpriv->buf_len); cpriv->state = P_HTML; cpriv->buf_len = 0; } else if (cpriv->buf_len < sizeof (cpriv->buf) - 1) cpriv->buf[cpriv->buf_len++] = ch; break; } } }