aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authortilghman <tilghman@f38db490-d61c-443f-a65b-d21fe96a405b>2008-12-02 22:56:36 +0000
committertilghman <tilghman@f38db490-d61c-443f-a65b-d21fe96a405b>2008-12-02 22:56:36 +0000
commit537c066ee59ee1f7f78adb6901a148cd032f3212 (patch)
tree544efedf7d2a092bccc41d52bc28373e6e5c76ee
parentb65162be4420d0726c6c2d8af387b434cb4ff775 (diff)
Merged revisions 152969,153122,154264,154268,154366,155399,155863,156166,156295,156690,156756,158066,158082,158540,158602,159276 via svnmerge from
https://origsvn.digium.com/svn/asterisk/trunk ................ r152969 | tilghman | 2008-10-30 15:35:46 -0500 (Thu, 30 Oct 2008) | 10 lines Merged revisions 152958 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/1.4 ........ r152958 | tilghman | 2008-10-30 15:33:28 -0500 (Thu, 30 Oct 2008) | 3 lines Cannot join detached threads. See http://www.opengroup.org/onlinepubs/000095399/functions/pthread_join.html (Closes issue #13400) ........ ................ r153122 | tilghman | 2008-10-31 11:35:21 -0500 (Fri, 31 Oct 2008) | 10 lines Merged revisions 153114 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/1.4 ........ r153114 | tilghman | 2008-10-31 11:30:32 -0500 (Fri, 31 Oct 2008) | 3 lines Turn off qualify on uncached realtime peers. (Closes issue #13383) ........ ................ r154264 | tilghman | 2008-11-04 12:59:48 -0600 (Tue, 04 Nov 2008) | 10 lines Recorded merge of revisions 154263 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/1.4 ........ r154263 | tilghman | 2008-11-04 12:58:05 -0600 (Tue, 04 Nov 2008) | 3 lines Make the monitor thread non-detached, so it can be joined (suggested by Russell on -dev list). ........ ................ r154268 | rmudgett | 2008-11-04 13:07:26 -0600 (Tue, 04 Nov 2008) | 11 lines Merged revisions 154266 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/1.4 ........ r154266 | rmudgett | 2008-11-04 13:01:08 -0600 (Tue, 04 Nov 2008) | 4 lines JIRA ABE-1703 mISDN sets the channel to the wrong state when it receives the indication AST_CONTROL_RINGING. ........ ................ r154366 | tilghman | 2008-11-04 14:51:18 -0600 (Tue, 04 Nov 2008) | 16 lines Merged revisions 154365 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/1.4 ........ r154365 | tilghman | 2008-11-04 14:49:33 -0600 (Tue, 04 Nov 2008) | 9 lines On busy systems, it's possible for the values checked within a single line of code to change, unless the structure is locked to ensure a consistent state. (closes issue #13717) Reported by: kowalma Patches: 20081102__bug13717.diff.txt uploaded by Corydon76 (license 14) Tested by: kowalma ........ ................ r155399 | tilghman | 2008-11-07 16:28:58 -0600 (Fri, 07 Nov 2008) | 14 lines Merged revisions 155398 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/1.4 ........ r155398 | tilghman | 2008-11-07 16:27:32 -0600 (Fri, 07 Nov 2008) | 7 lines Clarify error message. (closes issue #13809) Reported by: denke Patches: 20081104__bug13809.diff.txt uploaded by Corydon76 (license 14) Tested by: denke ........ ................ r155863 | mmichelson | 2008-11-10 15:14:44 -0600 (Mon, 10 Nov 2008) | 22 lines Merged revisions 155861 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/1.4 ........ r155861 | mmichelson | 2008-11-10 15:07:39 -0600 (Mon, 10 Nov 2008) | 14 lines Channel drivers assume that when their indicate callback is invoked, that the channel on which the callback was called is locked. This patch corrects an instance in chan_agent where a channel's indicate callback is called directly without first locking the channel. This was leading to some observed locking issues in chan_local, but considering that all channel drivers operate under the same expectations, the generic fix in chan_agent is the right way to go. AST-126 ........ ................ r156166 | russell | 2008-11-12 11:38:20 -0600 (Wed, 12 Nov 2008) | 15 lines Merged revisions 156164 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/1.4 ........ r156164 | russell | 2008-11-12 11:29:52 -0600 (Wed, 12 Nov 2008) | 7 lines Move the sanity check that makes sure "always fork" is not set along with the console option to be after the code that reads options from asterisk.conf. This resolves a situation where Asterisk can start taking up 100% when misconfigured. (Thanks to Bryce Porter (x86 on IRC) for letting me log in to his system to figure out what was causing the 100% CPU problem.) ........ ................ r156295 | tilghman | 2008-11-12 13:28:22 -0600 (Wed, 12 Nov 2008) | 13 lines Merged revisions 156294 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/1.4 ........ r156294 | tilghman | 2008-11-12 13:26:45 -0600 (Wed, 12 Nov 2008) | 6 lines If the SLA thread is not started, then reload causes a memory leak. (closes issue #13889) Reported by: eliel Patches: app_meetme.c.patch uploaded by eliel (license 64) ........ ................ r156690 | tilghman | 2008-11-13 15:30:41 -0600 (Thu, 13 Nov 2008) | 14 lines Merged revisions 156688 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/1.4 ........ r156688 | tilghman | 2008-11-13 15:24:00 -0600 (Thu, 13 Nov 2008) | 7 lines Provide more space for all the data which can appear in an originating channel name. (closes issue #13398) Reported by: bamby Patches: manager.c.diff uploaded by bamby (license 430) ........ ................ r156756 | tilghman | 2008-11-13 18:43:13 -0600 (Thu, 13 Nov 2008) | 13 lines Merged revisions 156755 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/1.4 ........ r156755 | tilghman | 2008-11-13 18:41:37 -0600 (Thu, 13 Nov 2008) | 6 lines ast_waitfordigit() requires that the channel be up, for no good logical reason. This prevents While/EndWhile from working within the "h" extension. Reported by: jgalarneau (for ABE C.2) Fixed by: me ........ ................ r158066 | mmichelson | 2008-11-20 11:39:06 -0600 (Thu, 20 Nov 2008) | 20 lines Merged revisions 158053 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/1.4 ........ r158053 | mmichelson | 2008-11-20 11:33:06 -0600 (Thu, 20 Nov 2008) | 12 lines Make sure to set the hangup cause on the calling channel in the case that ast_call() fails. For incoming SIP channels, this was causing us to send a 603 instead of a 486 when the call-limit was reached on the destination channel. (closes issue #13867) Reported by: still_nsk Patches: 13867.diff uploaded by putnopvut (license 60) Tested by: blitzrage ........ ................ r158082 | mmichelson | 2008-11-20 11:54:31 -0600 (Thu, 20 Nov 2008) | 24 lines Merged revisions 158071 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/1.4 ........ r158071 | mmichelson | 2008-11-20 11:48:42 -0600 (Thu, 20 Nov 2008) | 16 lines We don't handle 4XX responses to BYE well. According to section 15 of RFC 3261, we should terminate a dialog if we receive a 481 or 408 in response to our BYE. Since I am aware of at least one phone manufacturer who may sometimes send a 404 as well, I am being liberal and saying that any 4XX response to a BYE should result in a terminated dialog. (closes issue #12994) Reported by: pabelanger Patches: 12994.patch uploaded by putnopvut (license 60) Closes AST-129 ........ ................ r158540 | russell | 2008-11-21 16:12:37 -0600 (Fri, 21 Nov 2008) | 10 lines Merged revisions 158539 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/1.4 ........ r158539 | russell | 2008-11-21 16:05:55 -0600 (Fri, 21 Nov 2008) | 2 lines When compiling with DEBUG_THREADS, report the real file/func/line for ao2_lock/ao2_unlock ........ ................ r158602 | tilghman | 2008-11-21 17:14:11 -0600 (Fri, 21 Nov 2008) | 12 lines Merged revisions 158600 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/1.4 ........ r158600 | tilghman | 2008-11-21 17:07:46 -0600 (Fri, 21 Nov 2008) | 5 lines The passed extension may not be the same in the list as the current entry, because we strip spaces when copying the extension into the structure. Therefore, use the copied item to place the item into the list. (found by lmadsen on -dev, fixed by me) ........ ................ r159276 | tilghman | 2008-11-25 15:57:59 -0600 (Tue, 25 Nov 2008) | 14 lines Merged revisions 159269 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/1.4 ........ r159269 | tilghman | 2008-11-25 15:56:48 -0600 (Tue, 25 Nov 2008) | 7 lines Don't try to send a response on a NULL pvt. (closes issue #13919) Reported by: barthpbx Patches: chan_iax2.c.patch uploaded by eliel (license 64) Tested by: barthpbx ........ ................ git-svn-id: http://svn.digium.com/svn/asterisk/branches/1.6.0@160389 f38db490-d61c-443f-a65b-d21fe96a405b
-rw-r--r--apps/app_dial.c3
-rw-r--r--apps/app_meetme.c4
-rw-r--r--apps/app_while.c5
-rw-r--r--channels/chan_agent.c12
-rw-r--r--channels/chan_h323.c6
-rw-r--r--channels/chan_iax2.c11
-rw-r--r--channels/chan_misdn.c2
-rw-r--r--channels/chan_sip.c29
-rw-r--r--channels/chan_skinny.c2
-rw-r--r--include/asterisk/astobj2.h1
-rw-r--r--main/asterisk.c14
-rw-r--r--main/astobj2.c15
-rw-r--r--main/manager.c3
-rw-r--r--main/pbx.c2
14 files changed, 90 insertions, 19 deletions
diff --git a/apps/app_dial.c b/apps/app_dial.c
index 142fe9f25..ce2bffeb3 100644
--- a/apps/app_dial.c
+++ b/apps/app_dial.c
@@ -1583,6 +1583,9 @@ static int dial_exec_full(struct ast_channel *chan, void *data, struct ast_flags
/* Again, keep going even if there's an error */
ast_debug(1, "ast call on peer returned %d\n", res);
ast_verb(3, "Couldn't call %s\n", numsubst);
+ if (tc->hangupcause) {
+ chan->hangupcause = tc->hangupcause;
+ }
ast_hangup(tc);
tc = NULL;
ast_free(tmp);
diff --git a/apps/app_meetme.c b/apps/app_meetme.c
index 13f61df00..9f7f3afc3 100644
--- a/apps/app_meetme.c
+++ b/apps/app_meetme.c
@@ -1379,6 +1379,10 @@ static void sla_queue_event_full(enum sla_event_type type,
{
struct sla_event *event;
+ if (sla.thread == AST_PTHREADT_NULL) {
+ return;
+ }
+
if (!(event = ast_calloc(1, sizeof(*event))))
return;
diff --git a/apps/app_while.c b/apps/app_while.c
index 1c61d966e..405e78c3c 100644
--- a/apps/app_while.c
+++ b/apps/app_while.c
@@ -160,11 +160,16 @@ static int _while_exec(struct ast_channel *chan, void *data, int end)
return -1;
}
+#if 0
/* dont want run away loops if the chan isn't even up
this is up for debate since it slows things down a tad ......
+
+ Debate is over... this prevents While/EndWhile from working
+ within the "h" extension. Not good.
*/
if (ast_waitfordigit(chan,1) < 0)
return -1;
+#endif
for (x=0;;x++) {
if (get_index(chan, prefix, x)) {
diff --git a/channels/chan_agent.c b/channels/chan_agent.c
index ebfa11147..de7bb1125 100644
--- a/channels/chan_agent.c
+++ b/channels/chan_agent.c
@@ -657,9 +657,15 @@ static int agent_indicate(struct ast_channel *ast, int condition, const void *da
struct agent_pvt *p = ast->tech_pvt;
int res = -1;
ast_mutex_lock(&p->lock);
- if (p->chan && !ast_check_hangup(p->chan))
- res = p->chan->tech->indicate ? p->chan->tech->indicate(p->chan, condition, data, datalen) : -1;
- else
+ if (p->chan && !ast_check_hangup(p->chan)) {
+ while (ast_channel_trylock(p->chan)) {
+ ast_channel_unlock(ast);
+ usleep(1);
+ ast_channel_lock(ast);
+ }
+ res = p->chan->tech->indicate ? p->chan->tech->indicate(p->chan, condition, data, datalen) : -1;
+ ast_channel_unlock(p->chan);
+ } else
res = 0;
ast_mutex_unlock(&p->lock);
return res;
diff --git a/channels/chan_h323.c b/channels/chan_h323.c
index 26cf3a6b8..c24cbe71c 100644
--- a/channels/chan_h323.c
+++ b/channels/chan_h323.c
@@ -2609,7 +2609,7 @@ static int restart_monitor(void)
pthread_kill(monitor_thread, SIGURG);
} else {
/* Start a new monitor */
- if (ast_pthread_create_detached_background(&monitor_thread, NULL, do_monitor, NULL) < 0) {
+ if (ast_pthread_create_background(&monitor_thread, NULL, do_monitor, NULL) < 0) {
monitor_thread = AST_PTHREADT_NULL;
ast_mutex_unlock(&monlock);
ast_log(LOG_ERROR, "Unable to start monitor thread.\n");
@@ -3301,9 +3301,9 @@ static int unload_module(void)
}
if (!ast_mutex_lock(&monlock)) {
if ((monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) {
- /* this causes a seg, anyone know why? */
- if (monitor_thread != pthread_self())
+ if (monitor_thread != pthread_self()) {
pthread_cancel(monitor_thread);
+ }
pthread_kill(monitor_thread, SIGURG);
pthread_join(monitor_thread, NULL);
}
diff --git a/channels/chan_iax2.c b/channels/chan_iax2.c
index 2c2e11c52..107df395b 100644
--- a/channels/chan_iax2.c
+++ b/channels/chan_iax2.c
@@ -1664,12 +1664,21 @@ static int __find_callno(unsigned short callno, unsigned short dcallno, struct s
/* This will occur on the first response to a message that we initiated,
* such as a PING. */
+ if (dcallno) {
+ ast_mutex_lock(&iaxsl[dcallno]);
+ }
if (callno && dcallno && iaxs[dcallno] && !iaxs[dcallno]->peercallno && match(sin, callno, dcallno, iaxs[dcallno], check_dcallno)) {
iaxs[dcallno]->peercallno = callno;
res = dcallno;
store_by_peercallno(iaxs[dcallno]);
+ if (!res || !return_locked) {
+ ast_mutex_unlock(&iaxsl[dcallno]);
+ }
return res;
}
+ if (dcallno) {
+ ast_mutex_unlock(&iaxsl[dcallno]);
+ }
#ifdef IAX_OLD_FIND
/* If we get here, we SHOULD NOT find a call structure for this
@@ -6977,7 +6986,7 @@ static int update_registry(struct sockaddr_in *sin, int callno, char *devtype, i
/* Make sure our call still exists, an INVAL at the right point may make it go away */
if (!iaxs[callno]) {
- res = 0;
+ res = -1;
goto return_unref;
}
diff --git a/channels/chan_misdn.c b/channels/chan_misdn.c
index 15cdb7ce9..123971327 100644
--- a/channels/chan_misdn.c
+++ b/channels/chan_misdn.c
@@ -2479,7 +2479,7 @@ static int misdn_indication(struct ast_channel *ast, int cond, const void *data,
}
chan_misdn_log(3, p->bc->port, " --> * SEND: State Ring pid:%d\n", p->bc ? p->bc->pid : -1);
- ast_setstate(ast, AST_STATE_RINGING);
+ ast_setstate(ast, AST_STATE_RING);
if ( !p->bc->nt && (p->originator == ORG_MISDN) && !p->incoming_early_audio )
chan_misdn_log(2, p->bc->port, " --> incoming_early_audio off\n");
diff --git a/channels/chan_sip.c b/channels/chan_sip.c
index adf9ab905..05f63c61a 100644
--- a/channels/chan_sip.c
+++ b/channels/chan_sip.c
@@ -4280,8 +4280,11 @@ static int sip_call(struct ast_channel *ast, char *dest, int timeout)
res = update_call_counter(p, INC_CALL_RINGING);
- if (res == -1)
+ if (res == -1) {
return res;
+ } else {
+ ast->hangupcause = AST_CAUSE_USER_BUSY;
+ }
p->callingpres = ast->cid.cid_pres;
p->jointcapability = ast_translate_available_formats(p->capability, p->prefcodec);
@@ -15266,7 +15269,7 @@ static int handle_response_register(struct sip_pvt *p, int resp, char *rest, str
break;
case 200: /* 200 OK */
if (!r) {
- ast_log(LOG_WARNING, "Got 200 OK on REGISTER that isn't a register\n");
+ ast_log(LOG_WARNING, "Got 200 OK on REGISTER, but there isn't a registry entry for '%s' (we probably already got the OK)\n", S_OR(p->peername, p->username));
p->needdestroy = 1;
return 0;
}
@@ -15445,6 +15448,20 @@ static void handle_response(struct sip_pvt *p, int resp, char *rest, struct sip_
Fix assigned to Rizzo :-)
*/
/* check_via_response(p, req); */
+
+ /* RFC 3261 Section 15 specifies that if we receive a 408 or 481
+ * in response to a BYE, then we should end the current dialog
+ * and session. There is no mention in the spec of other 4XX responses,
+ * but it is known that at least one phone manufacturer potentially
+ * will send a 404 in response to a BYE, so we'll be liberal in what
+ * we accept and end the dialog and session if we receive any 4XX
+ * response to a BYE.
+ */
+ if (resp >= 400 && resp < 500 && sipmethod == SIP_BYE) {
+ p->needdestroy = 1;
+ return;
+ }
+
if (p->relatedpeer && p->method == SIP_OPTIONS) {
/* We don't really care what the response is, just that it replied back.
Well, as long as it's not a 100 response... since we might
@@ -20706,6 +20723,14 @@ static struct sip_peer *build_peer(const char *name, struct ast_variable *v, str
ast_log(LOG_WARNING, "Qualification of peer '%s' should be 'yes', 'no', or a number of milliseconds at line %d of sip.conf\n", peer->name, v->lineno);
peer->maxms = 0;
}
+ if (realtime && !ast_test_flag(&global_flags[1], SIP_PAGE2_RTCACHEFRIENDS) && peer->maxms > 0) {
+ /* This would otherwise cause a network storm, where the
+ * qualify response refreshes the peer from the database,
+ * which in turn causes another qualify to be sent, ad
+ * infinitum. */
+ ast_log(LOG_WARNING, "Qualify is incompatible with dynamic uncached realtime. Please either turn rtcachefriends on or turn qualify off on peer '%s'\n", peer->name);
+ peer->maxms = 0;
+ }
} else if (!strcasecmp(v->name, "qualifyfreq")) {
int i;
if (sscanf(v->value, "%d", &i) == 1)
diff --git a/channels/chan_skinny.c b/channels/chan_skinny.c
index f415ad6ca..ae6cc573d 100644
--- a/channels/chan_skinny.c
+++ b/channels/chan_skinny.c
@@ -5747,7 +5747,7 @@ static void *accept_thread(void *ignore)
sessions = s;
ast_mutex_unlock(&sessionlock);
- if (ast_pthread_create_detached(&tcp_thread, NULL, skinny_session, s)) {
+ if (ast_pthread_create(&tcp_thread, NULL, skinny_session, s)) {
destroy_session(s);
}
}
diff --git a/include/asterisk/astobj2.h b/include/asterisk/astobj2.h
index bb63496ca..322e4732c 100644
--- a/include/asterisk/astobj2.h
+++ b/include/asterisk/astobj2.h
@@ -211,6 +211,7 @@ int ao2_unlock(void *a);
#define ao2_unlock(a) _ao2_unlock(a, __FILE__, __PRETTY_FUNCTION__, __LINE__, #a)
int _ao2_unlock(void *a, const char *file, const char *func, int line, const char *var);
#endif
+int ao2_trylock(void *user_data);
/*!
*
diff --git a/main/asterisk.c b/main/asterisk.c
index 81c4c73b7..b8a95064d 100644
--- a/main/asterisk.c
+++ b/main/asterisk.c
@@ -3028,11 +3028,6 @@ int main(int argc, char *argv[])
if (ast_opt_console && !option_verbose)
ast_verbose("[ Booting...\n");
- if (ast_opt_always_fork && (ast_opt_remote || ast_opt_console)) {
- ast_log(LOG_WARNING, "'alwaysfork' is not compatible with console or remote console mode; ignored\n");
- ast_clear_flag(&ast_options, AST_OPT_FLAG_ALWAYS_FORK);
- }
-
/* For remote connections, change the name of the remote connection.
* We do this for the benefit of init scripts (which need to know if/when
* the main asterisk process has died yet). */
@@ -3043,8 +3038,10 @@ int main(int argc, char *argv[])
}
}
- if (ast_opt_console && !option_verbose)
+ if (ast_opt_console && !option_verbose) {
ast_verbose("[ Reading Master Configuration ]\n");
+ }
+
ast_readconfig();
if (ast_opt_remote && remotesock != NULL)
@@ -3053,6 +3050,11 @@ int main(int argc, char *argv[])
if (!ast_language_is_prefix && !ast_opt_remote)
ast_log(LOG_WARNING, "The 'languageprefix' option in asterisk.conf is deprecated; in a future release it will be removed, and your sound files will need to be organized in the 'new style' language layout.\n");
+ if (ast_opt_always_fork && (ast_opt_remote || ast_opt_console)) {
+ ast_log(LOG_WARNING, "'alwaysfork' is not compatible with console or remote console mode; ignored\n");
+ ast_clear_flag(&ast_options, AST_OPT_FLAG_ALWAYS_FORK);
+ }
+
if (ast_opt_dump_core) {
struct rlimit l;
memset(&l, 0, sizeof(l));
diff --git a/main/astobj2.c b/main/astobj2.c
index 77f0f2962..212b64ed9 100644
--- a/main/astobj2.c
+++ b/main/astobj2.c
@@ -170,6 +170,21 @@ int _ao2_unlock(void *user_data, const char *file, const char *func, int line, c
#endif
}
+int ao2_trylock(void *user_data)
+{
+ struct astobj2 *p = INTERNAL_OBJ(user_data);
+ int ret;
+
+ if (p == NULL)
+ return -1;
+ ret = ast_mutex_trylock(&p->priv_data.lock);
+#ifdef AO2_DEBUG
+ if (!ret)
+ ast_atomic_fetchadd_int(&ao2.total_locked, 1);
+#endif
+ return ret;
+}
+
/*
* The argument is a pointer to the user portion.
*/
diff --git a/main/manager.c b/main/manager.c
index e0ab9a16b..0076f64f3 100644
--- a/main/manager.c
+++ b/main/manager.c
@@ -2059,7 +2059,8 @@ static int action_command(struct mansession *s, const struct message *m)
/*! \brief helper function for originate */
struct fast_originate_helper {
char tech[AST_MAX_EXTENSION];
- char data[AST_MAX_EXTENSION];
+ /*! data can contain a channel name, extension number, username, password, etc. */
+ char data[512];
int timeout;
int format; /*!< Codecs used for a call */
char app[AST_MAX_APP];
diff --git a/main/pbx.c b/main/pbx.c
index 4c8f23caf..3a78612b3 100644
--- a/main/pbx.c
+++ b/main/pbx.c
@@ -6795,7 +6795,7 @@ int ast_add_extension2(struct ast_context *con,
}
res = 0; /* some compilers will think it is uninitialized otherwise */
for (e = con->root; e; el = e, e = e->next) { /* scan the extension list */
- res = ext_cmp(e->exten, extension);
+ res = ext_cmp(e->exten, tmp->exten);
if (res == 0) { /* extension match, now look at cidmatch */
if (!e->matchcid && !tmp->matchcid)
res = 0;