Wed Jan 8 2020 09:49:42

Asterisk developer's documentation


cdr.h
Go to the documentation of this file.
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 1999 - 2005, Digium, Inc.
5  *
6  * Mark Spencer <markster@digium.com>
7  *
8  * See http://www.asterisk.org for more information about
9  * the Asterisk project. Please do not directly contact
10  * any of the maintainers of this project for assistance;
11  * the project provides a web site, mailing lists and IRC
12  * channels for your use.
13  *
14  * This program is free software, distributed under the terms of
15  * the GNU General Public License Version 2. See the LICENSE file
16  * at the top of the source tree.
17  */
18 
19 /*!
20  * \file
21  * \brief Call Detail Record API
22  *
23  * \author Mark Spencer <markster@digium.com>
24  */
25 
26 #ifndef _ASTERISK_CDR_H
27 #define _ASTERISK_CDR_H
28 
29 #include <sys/time.h>
30 
31 #include "asterisk/data.h"
32 
33 /*!
34  * \brief CDR Flags
35  */
36 enum {
38  AST_CDR_FLAG_POSTED = (1 << 1),
39  AST_CDR_FLAG_LOCKED = (1 << 2),
40  AST_CDR_FLAG_CHILD = (1 << 3),
43  AST_CDR_FLAG_MAIN = (1 << 6),
44  AST_CDR_FLAG_ENABLE = (1 << 7),
48  AST_CDR_FLAG_DIALED = (1 << 11),
50 };
51 
52 /*!
53  * \brief CDR Flags - Disposition
54  */
55 enum {
57  AST_CDR_NULL = (1 << 0),
58  AST_CDR_FAILED = (1 << 1),
59  AST_CDR_BUSY = (1 << 2),
60  AST_CDR_ANSWERED = (1 << 3),
61 };
62 
63 /*!
64  * \brief CDR AMA Flags
65  */
66 enum {
70 };
71 
72 #define AST_MAX_USER_FIELD 256
73 #define AST_MAX_ACCOUNT_CODE 45
74 
75 /* Include channel.h after relevant declarations it will need */
76 #include "asterisk/channel.h"
77 #include "asterisk/utils.h"
78 
79 /*!
80  * \brief Responsible for call detail data
81  */
82 struct ast_cdr {
83  /*! Caller*ID with text */
85  /*! Caller*ID number */
87  /*! Destination extension */
89  /*! Destination context */
91 
93  /*! Destination channel if appropriate */
95  /*! Last application if appropriate */
97  /*! Last application data */
99 
100  struct timeval start;
101 
102  struct timeval answer;
103 
104  struct timeval end;
105  /*! Total time in system, in seconds */
106  long int duration;
107  /*! Total time call is up, in seconds */
108  long int billsec;
109  /*! What happened to the call */
110  long int disposition;
111  /*! What flags to use */
112  long int amaflags;
113  /*! What account number to use */
115  /*! Account number of the last person we talked to */
117  /*! flags */
118  unsigned int flags;
119  /*! Unique Channel Identifier
120  * 150 = 127 (max systemname) + "-" + 10 (epoch timestamp) + "." + 10 (monotonically incrementing integer) + NULL */
121  char uniqueid[150];
122  /* Linked group Identifier */
123  char linkedid[32];
124  /*! User field */
126  /*! Sequence field */
127  int sequence;
128 
129  /*! A linked list for variables */
131 
132  struct ast_cdr *next;
133 };
134 
135 int ast_cdr_isset_unanswered(void);
136 void ast_cdr_getvar(struct ast_cdr *cdr, const char *name, char **ret, char *workspace, int workspacelen, int recur, int raw);
137 int ast_cdr_setvar(struct ast_cdr *cdr, const char *name, const char *value, int recur);
138 int ast_cdr_serialize_variables(struct ast_cdr *cdr, struct ast_str **buf, char delim, char sep, int recur);
139 void ast_cdr_free_vars(struct ast_cdr *cdr, int recur);
140 int ast_cdr_copy_vars(struct ast_cdr *to_cdr, struct ast_cdr *from_cdr);
141 
142 /*!
143  * \brief CDR backend callback
144  * \warning CDR backends should NOT attempt to access the channel associated
145  * with a CDR record. This channel is not guaranteed to exist when the CDR
146  * backend is invoked.
147  */
148 typedef int (*ast_cdrbe)(struct ast_cdr *cdr);
149 
150 /*! \brief Return TRUE if CDR subsystem is enabled */
151 int check_cdr_enabled(void);
152 
153 /*!
154  * \brief Allocate a CDR record
155  * \retval a malloc'd ast_cdr structure
156  * \retval NULL on error (malloc failure)
157  */
158 struct ast_cdr *ast_cdr_alloc(void);
159 
160 /*!
161  * \brief Duplicate a record and increment the sequence number.
162  * \param cdr the record to duplicate
163  * \retval a malloc'd ast_cdr structure,
164  * \retval NULL on error (malloc failure)
165  * \see ast_cdr_dup()
166  * \see ast_cdr_dup_unique_swap()
167  */
168 struct ast_cdr *ast_cdr_dup_unique(struct ast_cdr *cdr);
169 
170 /*!
171  * \brief Duplicate a record and increment the sequence number of the old
172  * record.
173  * \param cdr the record to duplicate
174  * \retval a malloc'd ast_cdr structure,
175  * \retval NULL on error (malloc failure)
176  * \note This version increments the original CDR's sequence number rather than
177  * the duplicate's sequence number. The effect is as if the original CDR's
178  * sequence number was swapped with the duplicate's sequence number.
179  *
180  * \see ast_cdr_dup()
181  * \see ast_cdr_dup_unique()
182  */
183 struct ast_cdr *ast_cdr_dup_unique_swap(struct ast_cdr *cdr);
184 
185 /*!
186  * \brief Duplicate a record
187  * \param cdr the record to duplicate
188  * \retval a malloc'd ast_cdr structure,
189  * \retval NULL on error (malloc failure)
190  * \see ast_cdr_dup_unique()
191  * \see ast_cdr_dup_unique_swap()
192  */
193 struct ast_cdr *ast_cdr_dup(struct ast_cdr *cdr);
194 
195 /*!
196  * \brief Free a CDR record
197  * \param cdr ast_cdr structure to free
198  * Returns nothing
199  */
200 void ast_cdr_free(struct ast_cdr *cdr);
201 
202 /*!
203  * \brief Discard and free a CDR record
204  * \param cdr ast_cdr structure to free
205  * Returns nothing -- same as free, but no checks or complaints
206  */
207 void ast_cdr_discard(struct ast_cdr *cdr);
208 
209 /*!
210  * \brief Initialize based on a channel
211  * \param cdr Call Detail Record to use for channel
212  * \param chan Channel to bind CDR with
213  * Initializes a CDR and associates it with a particular channel
214  * \note The channel should be locked before calling.
215  * \return 0 by default
216  */
217 int ast_cdr_init(struct ast_cdr *cdr, struct ast_channel *chan);
218 
219 /*!
220  * \brief Initialize based on a channel
221  * \param cdr Call Detail Record to use for channel
222  * \param chan Channel to bind CDR with
223  * Initializes a CDR and associates it with a particular channel
224  * \note The channel should be locked before calling.
225  * \return 0 by default
226  */
227 int ast_cdr_setcid(struct ast_cdr *cdr, struct ast_channel *chan);
228 
229 /*!
230  * \brief Register a CDR handling engine
231  * \param name name associated with the particular CDR handler
232  * \param desc description of the CDR handler
233  * \param be function pointer to a CDR handler
234  * Used to register a Call Detail Record handler.
235  * \retval 0 on success.
236  * \retval -1 on error
237  */
238 int ast_cdr_register(const char *name, const char *desc, ast_cdrbe be);
239 
240 /*!
241  * \brief Unregister a CDR handling engine
242  * \param name name of CDR handler to unregister
243  * Unregisters a CDR by it's name
244  */
245 void ast_cdr_unregister(const char *name);
246 
247 /*!
248  * \brief Start a call
249  * \param cdr the cdr you wish to associate with the call
250  * Starts all CDR stuff necessary for monitoring a call
251  * Returns nothing
252  */
253 void ast_cdr_start(struct ast_cdr *cdr);
254 
255 /*! \brief Answer a call
256  * \param cdr the cdr you wish to associate with the call
257  * Starts all CDR stuff necessary for doing CDR when answering a call
258  * \note NULL argument is just fine.
259  */
260 void ast_cdr_answer(struct ast_cdr *cdr);
261 
262 /*!
263  * \brief A call wasn't answered
264  * \param cdr the cdr you wish to associate with the call
265  * Marks the channel disposition as "NO ANSWER"
266  * Will skip CDR's in chain with ANS_LOCK bit set. (see
267  * forkCDR() application.
268  */
269 extern void ast_cdr_noanswer(struct ast_cdr *cdr);
270 
271 /*!
272  * \brief Busy a call
273  * \param cdr the cdr you wish to associate with the call
274  * Marks the channel disposition as "BUSY"
275  * Will skip CDR's in chain with ANS_LOCK bit set. (see
276  * forkCDR() application.
277  * Returns nothing
278  */
279 void ast_cdr_busy(struct ast_cdr *cdr);
280 
281 /*!
282  * \brief Fail a call
283  * \param cdr the cdr you wish to associate with the call
284  * Marks the channel disposition as "FAILED"
285  * Will skip CDR's in chain with ANS_LOCK bit set. (see
286  * forkCDR() application.
287  * Returns nothing
288  */
289 void ast_cdr_failed(struct ast_cdr *cdr);
290 
291 /*!
292  * \brief Save the result of the call based on the AST_CAUSE_*
293  * \param cdr the cdr you wish to associate with the call
294  * \param cause the AST_CAUSE_*
295  * Returns nothing
296  */
297 int ast_cdr_disposition(struct ast_cdr *cdr, int cause);
298 
299 /*!
300  * \brief End a call
301  * \param cdr the cdr you have associated the call with
302  * Registers the end of call time in the cdr structure.
303  * Returns nothing
304  */
305 void ast_cdr_end(struct ast_cdr *cdr);
306 
307 /*!
308  * \brief Detaches the detail record for posting (and freeing) either now or at a
309  * later time in bulk with other records during batch mode operation.
310  * \param cdr Which CDR to detach from the channel thread
311  * Prevents the channel thread from blocking on the CDR handling
312  * Returns nothing
313  */
314 void ast_cdr_detach(struct ast_cdr *cdr);
315 
316 /*!
317  * \brief Spawns (possibly) a new thread to submit a batch of CDRs to the backend engines
318  * \param shutdown Whether or not we are shutting down
319  * Blocks the asterisk shutdown procedures until the CDR data is submitted.
320  * Returns nothing
321  */
322 void ast_cdr_submit_batch(int shutdown);
323 
324 /*!
325  * \brief Set the destination channel, if there was one
326  * \param cdr Which cdr it's applied to
327  * \param chan Channel to which dest will be
328  * Sets the destination channel the CDR is applied to
329  * Returns nothing
330  */
331 void ast_cdr_setdestchan(struct ast_cdr *cdr, const char *chan);
332 
333 /*!
334  * \brief Set the last executed application
335  * \param cdr which cdr to act upon
336  * \param app the name of the app you wish to change it to
337  * \param data the data you want in the data field of app you set it to
338  * Changes the value of the last executed app
339  * Returns nothing
340  */
341 void ast_cdr_setapp(struct ast_cdr *cdr, const char *app, const char *data);
342 
343 /*!
344  * \brief Set the answer time for a call
345  * \param cdr the cdr you wish to associate with the call
346  * \param t the answer time
347  * Starts all CDR stuff necessary for doing CDR when answering a call
348  * NULL argument is just fine.
349  */
350 void ast_cdr_setanswer(struct ast_cdr *cdr, struct timeval t);
351 
352 /*!
353  * \brief Set the disposition for a call
354  * \param cdr the cdr you wish to associate with the call
355  * \param disposition the new disposition
356  * Set the disposition on a call.
357  * NULL argument is just fine.
358  */
359 void ast_cdr_setdisposition(struct ast_cdr *cdr, long int disposition);
360 
361 /*!
362  * \brief Convert a string to a detail record AMA flag
363  * \param flag string form of flag
364  * Converts the string form of the flag to the binary form.
365  * \return the binary form of the flag
366  */
367 int ast_cdr_amaflags2int(const char *flag);
368 
369 /*!
370  * \brief Disposition to a string
371  * \param disposition input binary form
372  * Converts the binary form of a disposition to string form.
373  * \return a pointer to the string form
374  */
375 char *ast_cdr_disp2str(int disposition);
376 
377 /*!
378  * \brief Reset the detail record, optionally posting it first
379  * \param cdr which cdr to act upon
380  * \param flags |AST_CDR_FLAG_POSTED whether or not to post the cdr first before resetting it
381  * |AST_CDR_FLAG_LOCKED whether or not to reset locked CDR's
382  */
383 void ast_cdr_reset(struct ast_cdr *cdr, struct ast_flags *flags);
384 
385 /*! Reset the detail record times, flags */
386 /*!
387  * \param cdr which cdr to act upon
388  * \param flags |AST_CDR_FLAG_POSTED whether or not to post the cdr first before resetting it
389  * |AST_CDR_FLAG_LOCKED whether or not to reset locked CDR's
390  */
391 void ast_cdr_specialized_reset(struct ast_cdr *cdr, struct ast_flags *flags);
392 
393 /*! Flags to a string */
394 /*!
395  * \param flags binary flag
396  * Converts binary flags to string flags
397  * Returns string with flag name
398  */
399 char *ast_cdr_flags2str(int flags);
400 
401 /*!
402  * \brief Move the non-null data from the "from" cdr to the "to" cdr
403  * \param to the cdr to get the goodies
404  * \param from the cdr to give the goodies
405  */
406 void ast_cdr_merge(struct ast_cdr *to, struct ast_cdr *from);
407 
408 /*!
409  * \brief Set account code, will generate AMI event
410  * \note The channel should be locked before calling.
411  */
412 int ast_cdr_setaccount(struct ast_channel *chan, const char *account);
413 
414 /*!
415  * \brief Set the peer account
416  * \note The channel should be locked before calling.
417  */
418 int ast_cdr_setpeeraccount(struct ast_channel *chan, const char *account);
419 
420 /*!
421  * \brief Set AMA flags for channel
422  * \note The channel should be locked before calling.
423  */
424 int ast_cdr_setamaflags(struct ast_channel *chan, const char *amaflags);
425 
426 /*!
427  * \brief Set CDR user field for channel (stored in CDR)
428  * \note The channel should be locked before calling.
429  */
430 int ast_cdr_setuserfield(struct ast_channel *chan, const char *userfield);
431 /*!
432  * \brief Append to CDR user field for channel (stored in CDR)
433  * \note The channel should be locked before calling.
434  */
435 int ast_cdr_appenduserfield(struct ast_channel *chan, const char *userfield);
436 
437 
438 /*!
439  * \brief Update CDR on a channel
440  * \note The channel should be locked before calling.
441  */
442 int ast_cdr_update(struct ast_channel *chan);
443 
444 
445 extern int ast_default_amaflags;
446 
448 
449 struct ast_cdr *ast_cdr_append(struct ast_cdr *cdr, struct ast_cdr *newcdr);
450 
451 /*! \brief Reload the configuration file cdr.conf and start/stop CDR scheduling thread */
452 int ast_cdr_engine_reload(void);
453 
454 /*! \brief Load the configuration file cdr.conf and possibly start the CDR scheduling thread */
455 int ast_cdr_engine_init(void);
456 
457 /*! Submit any remaining CDRs and prepare for shutdown */
458 void ast_cdr_engine_term(void);
459 
460 /*!
461  * \brief
462  * \param[in] tree Where to insert the cdr.
463  * \param[in] cdr The cdr structure to insert in 'tree'.
464  * \param[in] recur Go throw all the cdr levels.
465  * \retval <0 on error.
466  * \retval 0 on success.
467  */
468 int ast_cdr_data_add_structure(struct ast_data *tree, struct ast_cdr *cdr, int recur);
469 
470 #endif /* _ASTERISK_CDR_H */
int ast_cdr_setamaflags(struct ast_channel *chan, const char *amaflags)
Set AMA flags for channel.
Definition: cdr.c:1042
int ast_cdr_disposition(struct ast_cdr *cdr, int cause)
Save the result of the call based on the AST_CAUSE_*.
Definition: cdr.c:790
void ast_cdr_submit_batch(int shutdown)
Spawns (possibly) a new thread to submit a batch of CDRs to the backend engines.
Definition: cdr.c:1270
int ast_cdr_setvar(struct ast_cdr *cdr, const char *name, const char *value, int recur)
Definition: cdr.c:343
int ast_cdr_isset_unanswered(void)
Definition: cdr.c:185
Main Channel structure associated with a channel.
Definition: channel.h:742
char accountcode[AST_MAX_ACCOUNT_CODE]
Definition: cdr.h:114
void ast_cdr_failed(struct ast_cdr *cdr)
Fail a call.
Definition: cdr.c:764
The data tree to be returned by the callbacks and managed by functions local to this file...
Definition: data.c:85
static int amaflags
Definition: chan_iax2.c:386
#define AST_MAX_USER_FIELD
Definition: cdr.h:72
char dstchannel[AST_MAX_EXTENSION]
Definition: cdr.h:94
void ast_cdr_reset(struct ast_cdr *cdr, struct ast_flags *flags)
Reset the detail record, optionally posting it first.
Definition: cdr.c:1149
void ast_cdr_end(struct ast_cdr *cdr)
End a call.
Definition: cdr.c:933
int ast_cdr_appenduserfield(struct ast_channel *chan, const char *userfield)
Append to CDR user field for channel (stored in CDR)
Definition: cdr.c:1069
long int billsec
Definition: cdr.h:108
struct ast_cdr * next
Definition: cdr.h:132
char dcontext[AST_MAX_EXTENSION]
Definition: cdr.h:90
int ast_cdr_setaccount(struct ast_channel *chan, const char *account)
Set account code, will generate AMI event.
Definition: cdr.c:990
Data retrieval API.
#define AST_MAX_ACCOUNT_CODE
Definition: cdr.h:73
struct ast_cdr * ast_cdr_dup(struct ast_cdr *cdr)
Duplicate a record.
Definition: cdr.c:213
char uniqueid[150]
Definition: cdr.h:121
void ast_cdr_setdisposition(struct ast_cdr *cdr, long int disposition)
Set the disposition for a call.
Definition: cdr.c:847
int sequence
Definition: cdr.h:127
char * ast_cdr_flags2str(int flags)
Definition: cdr.c:977
int value
Definition: syslog.c:39
int ast_default_amaflags
Definition: cdr.c:59
Utility functions.
int(* ast_cdrbe)(struct ast_cdr *cdr)
CDR backend callback.
Definition: cdr.h:148
int ast_cdr_data_add_structure(struct ast_data *tree, struct ast_cdr *cdr, int recur)
Definition: cdr.c:1674
int ast_cdr_setuserfield(struct ast_channel *chan, const char *userfield)
Set CDR user field for channel (stored in CDR)
Definition: cdr.c:1057
void ast_cdr_getvar(struct ast_cdr *cdr, const char *name, char **ret, char *workspace, int workspacelen, int recur, int raw)
Definition: cdr.c:264
int ast_cdr_setcid(struct ast_cdr *cdr, struct ast_channel *chan)
Initialize based on a channel.
Definition: cdr.c:883
char lastdata[AST_MAX_EXTENSION]
Definition: cdr.h:98
struct ast_cdr * ast_cdr_append(struct ast_cdr *cdr, struct ast_cdr *newcdr)
Definition: cdr.c:1216
long int amaflags
Definition: cdr.h:112
int ast_cdr_register(const char *name, const char *desc, ast_cdrbe be)
Register a CDR handling engine.
Definition: cdr.c:130
static const char app[]
Definition: app_adsiprog.c:49
General Asterisk PBX channel definitions.
char linkedid[32]
Definition: cdr.h:123
#define AST_MAX_EXTENSION
Definition: channel.h:135
void ast_cdr_answer(struct ast_cdr *cdr)
Answer a call.
Definition: cdr.c:737
char ast_default_accountcode[AST_MAX_ACCOUNT_CODE]
Definition: cdr.c:60
void ast_cdr_setanswer(struct ast_cdr *cdr, struct timeval t)
Set the answer time for a call.
Definition: cdr.c:834
char dst[AST_MAX_EXTENSION]
Definition: cdr.h:88
char channel[AST_MAX_EXTENSION]
Definition: cdr.h:92
struct ast_cdr * ast_cdr_dup_unique_swap(struct ast_cdr *cdr)
Duplicate a record and increment the sequence number of the old record.
Definition: cdr.c:200
int ast_cdr_update(struct ast_channel *chan)
Update CDR on a channel.
Definition: cdr.c:1083
int ast_cdr_engine_reload(void)
Reload the configuration file cdr.conf and start/stop CDR scheduling thread.
Definition: cdr.c:1668
static const char desc[]
Definition: cdr_radius.c:85
struct timeval answer
Definition: cdr.h:102
void ast_cdr_engine_term(void)
Definition: cdr.c:1663
Responsible for call detail data.
Definition: cdr.h:82
char lastapp[AST_MAX_EXTENSION]
Definition: cdr.h:96
int ast_cdr_serialize_variables(struct ast_cdr *cdr, struct ast_str **buf, char delim, char sep, int recur)
Definition: cdr.c:409
void ast_cdr_start(struct ast_cdr *cdr)
Start a call.
Definition: cdr.c:727
The descriptor of a dynamic string XXX storage will be optimized later if needed We use the ts field ...
Definition: strings.h:364
int ast_cdr_amaflags2int(const char *flag)
Convert a string to a detail record AMA flag.
Definition: cdr.c:1105
void ast_cdr_detach(struct ast_cdr *cdr)
Detaches the detail record for posting (and freeing) either now or at a later time in bulk with other...
Definition: cdr.c:1328
void ast_cdr_specialized_reset(struct ast_cdr *cdr, struct ast_flags *flags)
Definition: cdr.c:1192
unsigned int flags
Definition: cdr.h:118
void ast_cdr_merge(struct ast_cdr *to, struct ast_cdr *from)
Move the non-null data from the &quot;from&quot; cdr to the &quot;to&quot; cdr.
Definition: cdr.c:543
struct timeval start
Definition: cdr.h:100
static const char name[]
int ast_cdr_copy_vars(struct ast_cdr *to_cdr, struct ast_cdr *from_cdr)
Definition: cdr.c:383
long int duration
Definition: cdr.h:106
void ast_cdr_setapp(struct ast_cdr *cdr, const char *app, const char *data)
Set the last executed application.
Definition: cdr.c:822
int ast_cdr_setpeeraccount(struct ast_channel *chan, const char *account)
Set the peer account.
Definition: cdr.c:1016
Structure used to handle boolean flags.
Definition: utils.h:200
char src[AST_MAX_EXTENSION]
Definition: cdr.h:86
char peeraccount[AST_MAX_ACCOUNT_CODE]
Definition: cdr.h:116
struct ast_cdr * ast_cdr_dup_unique(struct ast_cdr *cdr)
Duplicate a record and increment the sequence number.
Definition: cdr.c:190
void ast_cdr_discard(struct ast_cdr *cdr)
Discard and free a CDR record.
Definition: cdr.c:488
struct timeval end
Definition: cdr.h:104
int ast_cdr_engine_init(void)
Load the configuration file cdr.conf and possibly start the CDR scheduling thread.
Definition: cdr.c:1646
void ast_cdr_noanswer(struct ast_cdr *cdr)
A call wasn&#39;t answered.
Definition: cdr.c:776
void ast_cdr_free(struct ast_cdr *cdr)
Free a CDR record.
Definition: cdr.c:475
long int disposition
Definition: cdr.h:110
int check_cdr_enabled(void)
Return TRUE if CDR subsystem is enabled.
Definition: cdr.c:120
char clid[AST_MAX_EXTENSION]
Definition: cdr.h:84
char * ast_cdr_disp2str(int disposition)
Disposition to a string.
Definition: cdr.c:959
void ast_cdr_setdestchan(struct ast_cdr *cdr, const char *chan)
Set the destination channel, if there was one.
Definition: cdr.c:812
void ast_cdr_free_vars(struct ast_cdr *cdr, int recur)
Definition: cdr.c:454
int ast_cdr_init(struct ast_cdr *cdr, struct ast_channel *chan)
Initialize based on a channel.
Definition: cdr.c:897
struct ast_cdr * ast_cdr_alloc(void)
Allocate a CDR record.
Definition: cdr.c:499
void ast_cdr_unregister(const char *name)
Unregister a CDR handling engine.
Definition: cdr.c:165
char userfield[AST_MAX_USER_FIELD]
Definition: cdr.h:125
void ast_cdr_busy(struct ast_cdr *cdr)
Busy a call.
Definition: cdr.c:753